在重复迭代期间更有效的改组

时间:2017-03-09 23:16:53

标签: python algorithm random

我需要对列表进行任意次数的迭代,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的性能损失?

1 个答案:

答案 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