生成具有给定数据集模式之外的随机唯一数字的列表[关闭]

问题描述 投票:0回答:2

我有以下列表(作为 CSV 文件中的简单数据集)。一些列表包含连续的、非重复的整数,而其他列表则包含遵循某种模式的非重复的唯一数字:

sample-list-1.csv

N = 5

list1 = [1,  2,  3,  4,  5]
list2 = [2,  3,  4,  5,  6]
list3 = [1,  7, 13, 19, 25]
list4 = [7, 13, 19, 25, 31]

...等等。每个列表都位于单独的行中,每个数字位于单独的列中 - CSV 中没有标题或索引。

仔细观察,列表中的数字可能代表一个矩阵,这是完全正确的,但是 N+1...即 6x6 矩阵:

6 x 6 matrix

1   2   3   4   5   6
7   8   9   10  11  12
13  14  15  16  17  18
19  20  21  22  23  24
25  26  27  28  29  30
31  32  33  34  35  36

我的目标是生成另一个列表(或多个列表),其中包含“N”个非连续、非重复、唯一/随机数字,这些数字不遵循原始列表数据集中的模式。当然,这 N 个数字应该在矩阵的 36 个数字中。

也可以考虑最多连续 2 个连续数字或 2 个连续数字(按列)的误差范围,但生成的列表中的其他数字应遵循上述规则。

到目前为止,我能够导入 CSV 文件,并能够使用简单的代码生成随机、不重复的数字列表:

import random
import csv

N = 5
pick = random.sample(range(1, (N*N)+1), N-1)
#print("pick:", pick)

with open('sample-list-1.csv', newline = '') as f:
    reader = csv.reader(f)
    csvdata = list(reader)

csvdata_list = [int(x) for x in csvdata[2]]
#print("csvdata_list:", csvdata_list)

for n in pick:
    for i in csvdata_list:
        if n == i:
            print("n=", n, "i=", i)

我可以使用

for
循环与原始数据集和随机数列表进行一些简单的比较。但是,我当前的方法一次仅迭代一个列表/模式,并且我希望迭代多个列表及其模式以在新列表中生成唯一性。

关于如何使用代码在原始数据集中的模式之外实现真正的随机性,有什么想法吗?

我应该早先提到这一点,矩阵本身在这个问题中并没有发挥任何重要作用。它只是作为一个示例来显示原始数据集中的“模式”。问题主要是关于原始数据集列表和新生成的列表。

仅供参考,我正在创建一个看起来像矩阵(带有节点编号)的networkx图,并且每次迭代/运行,我将原始数据集中的节点编号突出显示为“黄色”,然后随机生成的节点编号为“绿色”,其余节点为“红色”。

python list random networkx
2个回答
0
投票

如果你想要真正的随机集,那么强迫它避免某种模式也会创建一个不太严格的模式。

最随机的方式是让它对每个索引完全随机选择。如果您不想重复,只需使用不放回的抽样方法即可。

以随机顺序重用现有集合中所有值的一种简单方法是使用

random.shuffle()

new_list=csvdata_list
random.shuffle(new_list)

需要注意的是,随机洗牌是就地进行的,这意味着它会重新排列您当前的列表,因此您需要复制列表然后对其进行洗牌。这样就不会重复,所有的数字和真正的随机性。

您始终可以创建一个函数来检查连续两个以上的情况,删除系列中的第三个,并使用一些规则扩展列表,以防止它创建另一个系列,但它会减少一些随机因素。

如果目标是随机性,那么不受约束是关键。

如果您需要它没有连续的值或级数,那么这是一个不同的标准,但会与真正的随机性相矛盾,因为在真正随机的情况下可能会发生序列和级数。关键是它们肯定会本地化。


0
投票

我将在这里使用一些“技巧”:

  • 展平矩阵:
    [item for row in rows for item in row]
  • 列表中真实值的计数:
    sum(bool(item) for item in items)
  • 转置矩阵:
    list(zip(*matrix))
  • 获取连续对的列表项:
    zip(items, items[1:])
  • 对列表进行分块:
    [items[i:i+size] for i in range(0, len(items), size)]

有了这些,我将创建两个辅助函数。

一个用于打乱矩阵中的项目的:

def scramble(data):
    column_count = len(data[0])
    items = [item for row in data for item in row]
    random.shuffle(items)

    return [
        items[index: index + column_count]
        for index
        in range(0, len(items), column_count)
    ]

第二个测试一行是否少于一定数量的连续值。

def is_valid_row(row, max_consecutives=0):
    consecutive_count = sum(abs(a - b) <= 1 for a, b in zip(row, row[1:]))
    return consecutive_count <= max_consecutives

现在我们可以尝试不断生成候选矩阵,直到找到一个好的矩阵。当然,如果您愿意,您可以在此处添加一个计数器,以便在失败一定次数后放弃:

data = [
    [1,  2,  3,  4,  5],
    [2,  3,  4,  5,  6],
    [1,  7, 13, 19, 25],
    [7, 13, 19, 25, 31],
]

i = 0
while True:
    i += 1
    print(f"Testing Candidate Matrix: {i}", end="\r", flush=True)

    candidate = scramble(data)
    if all(is_valid_row(row) for row in candidate):
        if all(is_valid_row(row) for row in zip(*candidate)):
            print()
            break

print("Candidate found:")
for row in candidate:
    print(f"\t{row}")

这应该给你类似的东西:

Testing Candidate Matrix: 511
Candidate found:
        [2, 31, 25, 13, 2]
        [19, 4, 1, 3, 7]
        [3, 13, 5, 7, 4]
        [19, 5, 25, 1, 6]
© www.soinside.com 2019 - 2024. All rights reserved.