问题描述
假设我要随机编号,但是该编号不能为i
或列表中已经存在的编号。如何检查if
语句中的列表?
我想我已经接近答案了
if randlink == i or (randlink == x for x in listofnumbers):
return randNumber(i,listofnumbers)
def randNumber(i,listofnumbers):
from random import randrange
randlink = randrange(0,size)
if randlink == i or [randlink == x for x in listofnumbers]:
return randNumber(i,listofnumbers)
return randlink
解决方法
您要查找的运算符是in
:
if randlink == i or randlink in listofnumbers:
...
在这种情况下,递归不是一个好主意,因为您的代码可能会搜索很长时间。改为使用循环:
randlink = randrange(0,size)
while randlink == i or randlink in listofnumbers:
randlink = randrange(0,size)
return randlink
不要使用列表,因为它具有线性查找。改用一组:
s = set(listofnumbers)
在函数外执行一次。查找的界面相同:
while randlink == i or randlink in s:
最后,带有拒绝的采样通常不是最佳的。更好的方法是弄清楚如何将采样映射到所需范围。
在您的代码中,您没有显示i
,listofnumbers
和size
之间的明确关联。您暗示这是在不实例化的大范围内进行采样而不替换的尝试。函数random.sample
就是为此目的而创建的。如果将range(size)
作为序列传递,则无论size
有多大,都只需分配实际选取的样本。
假设您要生成n
个样本,而i
是您要避免的随机数。 random.sample
的约定是,任何子集都具有相同的一致性,因此您可以执行以下操作:
numbers = set(random.sample(range(size),n + 1))
try:
numbers.remove(i)
except KeyError:
numbers.pop()
如果您确实想保留random.sample
返回的原始订单,则可以做一些额外的工作:
numbers = random.sample(range(size),n + 1)
try:
numbers.remove(i)
except ValueError:
numbers.pop()
在这种情况下,list
界面与set
几乎相同,但速度慢得多。唯一的区别是异常类型。
您可以使用
检查它是否在列表中if randlink in listofnumbers: