Pourquoi random.shuffle
revient None
en Python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Comment obtenir la valeur mélangée au lieu de None
?
Pourquoi random.shuffle
revient None
en Python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Comment obtenir la valeur mélangée au lieu de None
?
Réponses:
random.shuffle()
modifie la x
liste en place .
Les méthodes d'API Python qui modifient une structure sur place renvoient généralement None
, et non la structure de données modifiée.
Si vous souhaitez créer une nouvelle liste aléatoire basée sur une liste existante, où la liste existante est conservée dans l'ordre, vous pouvez utiliser random.sample()
avec toute la longueur de l'entrée:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
Vous pouvez également utiliser sorted()
avec random.random()
pour une clé de tri:
shuffled = sorted(x, key=lambda k: random.random())
mais cela invoque le tri (une opération O (NlogN)), tandis que l'échantillonnage à la longueur d'entrée ne prend que des opérations O (N) (le même processus que celui random.shuffle()
utilisé, l'échange de valeurs aléatoires à partir d'un pool de réduction).
Démo:
>>> 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']
key
fonction à valeur aléatoire est-elle vraiment garantie? Certains algorithmes de tri rapide tombent si les comparaisons ne sont pas cohérentes. Je peux voir que cela fonctionne de toute façon, en fonction de l'implémentation (decorate-sort-undecorate n'aura besoin de s'appliquer key
qu'une seule fois sur chaque élément donc sera bien défini).
key
appelable. Donc oui, c'est garanti car chaque valeur reçoit sa clé aléatoire exactement une fois.
Selon la documentation :
Mélangez la séquence x en place. L'argument optionnel random est une fonction à 0 argument retournant un flottant aléatoire dans [0.0, 1.0); par défaut, c'est la fonction random ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffle
modifie la liste en place. C'est bien, car copier une grande liste serait une surcharge si vous n'avez plus besoin de la liste d'origine.
Selon le « explicite est mieux que implicite » principe de style de pythonique , retournant la liste serait une mauvaise idée, car alors on pourrait penser qu'il est un nouveau bien en fait , il n'est pas.
Si vous avez besoin d' une nouvelle liste, vous devrez écrire quelque chose comme
new_x = list(x) # make a copy
random.shuffle(new_x)
ce qui est bien explicite. Si vous avez fréquemment besoin de cet idiome, enveloppez-le dans une fonction shuffled
(voir sorted
) qui renvoie new_x
.
J'ai eu mon moment aha avec ce concept comme celui-ci:
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']
Les API Python qui modifient la structure en place elles-mêmes retournent None en sortie.
list = [1,2,3,4,5,6,7,8]
print(list)
Sortie: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle
print(shuffle(list))
Sortie: Aucun
from random import sample
print(sample(list, len(list)))
Sortie: [7, 3, 2, 4, 5, 6, 1, 8]
Vous pouvez retourner la liste aléatoire en utilisant random.sample()
comme expliqué par d'autres. Il fonctionne en échantillonnant k éléments de la liste sans remplacement . Donc, s'il y a des éléments en double dans votre liste, ils seront traités de manière unique.
>>> 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]