我已经查看了与该问题类似的几个答案,而且似乎所有人都提供了很好的oneliner答案,但是,仅解决了通过删除重复项使列表唯一的事实。我需要列表中有5。
我唯一能想到的代码就是这样:
from random import *
tuples = []
while len(tuples) < 5:
rand = (randint(0, 6), randint(0,6))
if rand not in tuples:
tuples.append(rand)
我觉得有一种更简单的方法,但我不知道。我尝试从随机玩sample():
sample((randint(0,6), randint(0,6)), 5)
但是这给了我一个“样本大于总体或为负”错误。
一种快速方法是使用itertools.product
生成所有元组可能性,然后使用sample
从中选择5个:
from itertools import product
from random import sample
sample(list(product(range(7), repeat=2)), k=5)
对于这么少的一组输入,只需生成所有可能的输出,然后将它们sample
:
import itertools
import random
size = 6
random.sample(list(itertools.product(range(size+1), repeat=2)), 5)
尽管您指出界限(size
)可能是一个参数,并且如果界限可能更大,这可能是个问题(您将生成size ** 2
tuple
s以选择[ C0],并且内存使用情况可能会失控)。如果这是一个问题,考虑到您只需要一对整数,则有一个便宜的技巧:选择one随机整数,对两个结果整数进行编码,然后对其进行解码。例如:
5
由于size = 6
raw_sample = random.sample(range((size + 1) ** 2), 5)
decoded_sample = [divmod(x, size+1) for x in raw_sample)]
的开销为零(内存使用情况与长度无关),您可以从中精确选择五个值,开销与所选的五个成正比,而不是49个可能的结果。然后,您可以根据单个值的范围(在这种情况下,包括0到range
,所以size
个可能的值)的范围来计算商和余数,从而便宜地获得高和低结果。
性能差异非常明显;比较:
size + 1
至:
def unique_random_pairs_by_product(size):
return random.sample(list(itertools.product(range(size+1), repeat=2)), 5)
def unique_random_pairs_optimized(size):
val_range = size + 1
return [divmod(x, val_range) for x in random.sample(range(val_range * val_range), 5)]
版本花费的时间甚至比参数optimized
少15%(6
为〜4.65μs,product
为〜3.95μs)。但是在optimized
的size
下,您根本看不到比例因子。对于6
,size=100
仅增加到〜4.35μs(时间略有增加,因为较大的optimized
更有可能不得不分配新的range
,而不是使用较小的int
缓存),而int
跃升至387μs,相差近100倍。对于product
,size=1000
的时间跳至63.8 ms,而product
保持〜4.35μs;运行时间相差10,000倍(并且内存使用率甚至更高)。如果optimized
大于该值,则基于size
的解决方案将迅速达到人类甚至注意到一次采样的延迟的程度。 product
解决方案将继续以相同的性能运行(optimized
的成本具有难以置信的微小差异)。