为什么random.shuffle返回None?


88

为什么要用Pythonrandom.shuffle返回None

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None

我如何获得改组后的值而不是None


不是随机值,而是列表的随机改组。
alvas


Answers:


157

random.shuffle()更改x列表到位

在原位更改结构的Python API方法通常返回None,而不是修改后的数据结构。

如果要基于现有列表创建新的随机混排列表,并按顺序保留现有列表,则可以使用random.sample()输入的完整长度:

x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))     

您还可以将sorted()withrandom.random()用于排序键:

shuffled = sorted(x, key=lambda k: random.random())

但这会调用排序(O(NlogN)操作),而采样到输入长度仅需要O(N)操作(与random.shuffle()所使用的过程相同,即从收缩池中换出随机值)。

演示:

>>> import random
>>> x = ['foo', 'bar', 'black', 'sheep']
>>> random.sample(x, len(x))
['bar', 'sheep', 'black', 'foo']
>>> sorted(x, key=lambda k: random.random())
['sheep', 'foo', 'black', 'bar']
>>> x
['foo', 'bar', 'black', 'sheep']

2
使用随机值key函数真的可以保证吗?如果比较不一致,则某些快速排序算法会失败。我可以看到这两种方式都有效,具体取决于实现方式(decorate-sort-undecorate只需key在每个元素上应用一次,因此定义明确)。
torek

2
@torek:在对key可调用对象进行排序时,Python使用decorate-sort-undecorate 。是的,因此可以保证每个值都被赋予一次随机键。
的Martijn Pieters的

35

此方法也适用。

import random
shuffled = random.sample(original, len(original))

8

根据文档

将序列x洗净。可选参数random是一个0参数的函数,返回[0.0,1.0)中的一个随机浮点数;默认情况下,这是函数random()。

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']

6

真的吗

1.效率

shuffle修改列表到位。这很好,因为如果您不再需要原始列表,则复制大列表将是纯开销。

2. Python风格

根据pythonic样式“显式胜于隐式”原则,返回列表将是一个坏主意,因为那时人们可能认为它一个新列表,尽管实际上并非如此。

但是我不喜欢这样!

如果您确实需要新的清单,则必须编写类似

new_x = list(x)  # make a copy
random.shuffle(new_x)

这是很明确的。如果您经常需要该惯用法,请将其包装在一个返回return的函数中shuffled(请参阅参考资料sortednew_x


2

我很喜欢这个概念,像这样:

from random import shuffle
x = ['foo','black','sheep'] #original list
y = list(x) # an independent copy of the original
for i in range(5):
    print shuffle(y) # shuffles the original "in place" prints "None" return
    print x,y #prints original, and shuffled independent copy

>>>
None
['foo', 'black', 'sheep'] ['foo', 'black', 'sheep']
None
['foo', 'black', 'sheep'] ['black', 'foo', 'sheep']
None
['foo', 'black', 'sheep'] ['sheep', 'black', 'foo']
None
['foo', 'black', 'sheep'] ['black', 'foo', 'sheep']
None
['foo', 'black', 'sheep'] ['sheep', 'black', 'foo']

因为python默认情况下会执行“按值复制”,而不是通过引用传递=)stackoverflow.com/a/986495/610569
alvas

2

本身更改结构的Python API会返回None作为输出。

list = [1,2,3,4,5,6,7,8]
print(list)

输出:[1、2、3、4、5、6、7、8]

from random import shuffle
print(shuffle(list))

输出:无

from random import sample
print(sample(list, len(list)))

输出:[7、3、2、4、5、6、1、8]


0

您可以random.sample()按照其他人的说明使用,返回混洗后的列表。它通过从列表中采样k个元素而不进行替换来工作。因此,如果列表中有重复的元素,则将对它们进行唯一处理。

>>> l = [1,4,5,3,5]
>>> random.sample(l,len(l))
[4, 5, 5, 3, 1]
>>> random.sample(l,len(l)-1)
[4, 1, 5, 3]
>>> random.sample(l,len(l)-1)
[3, 5, 5, 1]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.