我需要对列表进行任意次数的迭代,yield
以随机顺序排列列表中的每个元素(每次迭代完整列表时都会有不同的顺序)。我需要在第二次产生该元素之前产生一次元素,在第三次产生该元素之前产生两次元素,等等。
目前,我的代码如下所示:
def random_yield(data):
random.shuffle(data)
data_index = 0
while True:
yield data[data_index]
data_index += 1
if data_index == len(data):
random.shuffle(data)
data_index = 0
有没有办法更有效地执行此操作,因此我不会在random.shuffle()
len(data)
之后支付yield
的性能损失?
答案 0 :(得分:3)
每次迭代都可以执行Fisher-Yates shuffle一步,从而在每次迭代中均匀分配成本。这不是更有效 - 事实上,考虑到库函数可能比Python代码更快,它可能效率较低 - 但它避免了长时间停顿。
代码与每次抓取随机元素没有显着区别。唯一的区别是你从向量的子集中获取随机元素:
from random import randrange
def random_yield(data):
index = 0
limit = len(data)
while True:
if index + 1 >= limit:
yield data[index]
index = 0
else:
# Get a random element which we haven't yet used this cycle
# (This is a single iteration of the F-Y shuffle algorithm)
j = randrange(index, limit)
rv = data[j]
yield rv
# Swap the element we just selected so its not in the next subrange
data[j] = data[index]
data[index] = rv
index += 1