Pythonic方法生成一个没有重复项的特定大小的列表?
我试图生成一个大小为Pythonic方法生成一个没有重复项的特定大小的列表?,python,Python,我试图生成一个大小为num\u cities的(x,y)元组列表,约束条件是没有两个元组是相同的。是否有一种更短的、类似于python的方法可以使用set-comprehension或itertools?我目前有: def make_random_cities(num_cities, max_x, max_y): cities = set() while len(cities) < num_cities: x, y = randint(0, max_
num\u cities
的(x,y)
元组列表,约束条件是没有两个元组是相同的。是否有一种更短的、类似于python的方法可以使用set-comprehension或itertools
?我目前有:
def make_random_cities(num_cities, max_x, max_y):
cities = set()
while len(cities) < num_cities:
x, y = randint(0, max_x), randint(0, max_y)
cities.add((x, y))
return list(cities)
def生成随机城市(数量城市、最大城市x、最大城市y):
城市=集合()
而len(城市)
如果最大值不太大,无法在内存中存储完整的可能性集(并且不会永远生成它们),并且可以在此处有效使用:
import itertools
import random
def make_random_cities(num_cities, max_x, max_y):
return random.sample(list(itertools.product(range(max_x+1), range(max_y+1))), num_cities)
如果输入的产品
太大,很容易超出主内存;在这种情况下,循环直到获得足够的唯一结果的方法可能是最好的方法
您可以独立地对每个范围进行采样,然后将它们组合在一起,但这会为每个轴添加唯一性约束,我猜这是您不想要的
对于这种特殊情况(遵循可预测模式的唯一数字),您可以使用一种技巧使该内存友好,同时仍然避免任意长循环的问题。您可以生成一个范围
(或者在Py2中,xrange
)来将产品
中的两个唯一值编码为一个值,而不是将范围
中的产品
作为一个值:
def make_random_cities(num_cities, max_x, max_y):
max_xy = (max_x+1) * (max_y+1)
xys = random.sample(range(max_xy), num_cities)
return [divmod(xy, max_y+1) for xy in xys]
这意味着您没有要存储的大型中间数据(因为Py3range
/Py2xrange
是“虚拟”序列,其存储要求与它们所代表的值的范围无关,并且是随机的。sample
生成样本而不需要读取底层序列的所有值).如果最大值不太大,无法在内存中存储完整的可能性集(并且不会永远生成它们),并且可以在此处有效使用:
import itertools
import random
def make_random_cities(num_cities, max_x, max_y):
return random.sample(list(itertools.product(range(max_x+1), range(max_y+1))), num_cities)
如果输入的产品
太大,很容易超出主内存;在这种情况下,循环直到获得足够的唯一结果的方法可能是最好的方法
您可以独立地对每个范围进行采样,然后将它们组合在一起,但这会为每个轴添加唯一性约束,我猜这是您不想要的
对于这种特殊情况(遵循可预测模式的唯一数字),您可以使用一种技巧使该内存友好,同时仍然避免任意长循环的问题。您可以生成一个范围
(或者在Py2中,xrange
)来将产品
中的两个唯一值编码为一个值,而不是将范围
中的产品
作为一个值:
def make_random_cities(num_cities, max_x, max_y):
max_xy = (max_x+1) * (max_y+1)
xys = random.sample(range(max_xy), num_cities)
return [divmod(xy, max_y+1) for xy in xys]
这意味着您没有要存储的大型中间数据(因为Py3range
/Py2xrange
是“虚拟”序列,其存储要求与它们所代表的值的范围无关,并且是随机的。sample
生成样本而不需要读取底层序列的所有值).如果城市数量远小于max\u x*max\u y
,则您当前的代码可能是好的。如果它们靠得更近,生成重复坐标可能会浪费很多时间
另一种方法是生成所有可能的坐标,然后从中采样:
possible_coords = list(itertools.product(range(max_x), range(max_y))
sample = random.sample(possible_coords, len(cities))
生成城市列表总是需要O(max_x*max_y)
,但如果城市数量增加,情况不会变得更糟。如果城市数量远小于max_x*max_y
,则您当前的代码可能很好。如果它们靠得更近,生成重复坐标可能会浪费很多时间
另一种方法是生成所有可能的坐标,然后从中采样:
possible_coords = list(itertools.product(range(max_x), range(max_y))
sample = random.sample(possible_coords, len(cities))
生成城市列表总是需要O(max\u x*max\u y)
,但如果城市数量增加,情况不会变得更糟