Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pythonic方法生成一个没有重复项的特定大小的列表?_Python - Fatal编程技术网

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]

这意味着您没有要存储的大型中间数据(因为Py3
range
/Py2
xrange
是“虚拟”序列,其存储要求与它们所代表的值的范围无关,并且是随机的。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]

这意味着您没有要存储的大型中间数据(因为Py3
range
/Py2
xrange
是“虚拟”序列,其存储要求与它们所代表的值的范围无关,并且是随机的。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)
,但如果城市数量增加,情况不会变得更糟