我有以下列表(作为 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图,并且每次迭代/运行,我将原始数据集中的节点编号突出显示为“黄色”,然后随机生成的节点编号为“绿色”,其余节点为“红色”。
如果你想要真正的随机集,那么强迫它避免某种模式也会创建一个不太严格的模式。
最随机的方式是让它对每个索引完全随机选择。如果您不想重复,只需使用不放回的抽样方法即可。
以随机顺序重用现有集合中所有值的一种简单方法是使用
random.shuffle()
new_list=csvdata_list
random.shuffle(new_list)
需要注意的是,随机洗牌是就地进行的,这意味着它会重新排列您当前的列表,因此您需要复制列表然后对其进行洗牌。这样就不会重复,所有的数字和真正的随机性。
您始终可以创建一个函数来检查连续两个以上的情况,删除系列中的第三个,并使用一些规则扩展列表,以防止它创建另一个系列,但它会减少一些随机因素。
如果目标是随机性,那么不受约束是关键。
如果您需要它没有连续的值或级数,那么这是一个不同的标准,但会与真正的随机性相矛盾,因为在真正随机的情况下可能会发生序列和级数。关键是它们肯定会本地化。
我将在这里使用一些“技巧”:
[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]