如何在生成器上使用random.shuffle()?蟒蛇

alv*_*vas 14 python random shuffle list generator

如何在生成器上使用random.shuffle()而不从生成器初始化列表?这甚至可能吗?如果没有,我应该如何random.shuffle()在我的名单上使用?

>>> import random
>>> random.seed(2)
>>> x = [1,2,3,4,5,6,7,8,9]
>>> def yielding(ls):
...     for i in ls:
...             yield i
... 
>>> for i in random.shuffle(yielding(x)):
...     print i
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/random.py", line 287, in shuffle
    for i in reversed(xrange(1, len(x))):
TypeError: object of type 'generator' has no len()
Run Code Online (Sandbox Code Playgroud)

注意:random.seed()是否设计为在每个脚本运行后返回相同的输出?

Mar*_*ers 29

为了统一调整序列,random.shuffle()需要知道输入的时间长度.发电机不能提供这个; 你必须将它具体化为一个列表:

lst = list(yielding(x))
random.shuffle(lst)
for i in lst:
    print i
Run Code Online (Sandbox Code Playgroud)

相反,你可以使用sorted()with random.random()作为键:

for i in sorted(yielding(x), key=lambda k: random.random()):
    print i
Run Code Online (Sandbox Code Playgroud)

但由于这产生了一个清单,所以走这条路是没有意义的.

演示:

>>> import random
>>> x = [1,2,3,4,5,6,7,8,9]
>>> sorted(iter(x), key=lambda k: random.random())
[9, 7, 3, 2, 5, 4, 6, 1, 8]
Run Code Online (Sandbox Code Playgroud)


stu*_*ter 6

根据情况,如果您提前知道有多少数据,则可以对数据进行索引,并根据混洗索引对其进行计算/读取。这相当于:“不要使用生成器来解决这个问题”,如果没有特定的用例,就很难想出通用的方法。

或者...如果您需要使用发电机...

这取决于您想要数据的“洗牌程度”。当然,正如人们指出的那样,发电机没有长度,因此您需要在某些时候评估发电机,这可能会很昂贵。如果不需要完美的随机性,可以引入 shuffle buffer:

from itertools import islice

import numpy as np


def shuffle(generator, buffer_size):
    while True:
        buffer = list(islice(generator, buffer_size))
        if len(buffer) == 0:
            break
        np.random.shuffle(buffer)
        for item in buffer:
            yield item


shuffled_generator = shuffle(my_generator, 256)

Run Code Online (Sandbox Code Playgroud)

这会将数据分成大块buffer_size,因此如果这是您的限制因素,您可以避免内存问题。当然,这不是真正的随机洗牌,因此它不应该用于已排序的内容,但如果您只需要为数据添加一些随机性,这可能是一个很好的解决方案。


Aar*_*lla 5

如果不临时将所有元素保存在某处,就不可能随机化生成器的产量。幸运的是,这在 Python 中非常简单:

tmp = list(yielding(x))
random.shuffle(tmp)
for i in tmp:
    print i
Run Code Online (Sandbox Code Playgroud)

请注意对它的调用list()将读取所有项目并将它们放入列表中。

如果您不想或无法存储所有元素,则需要更改生成器以按随机顺序生成。