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))
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).
L'utilisation d'une keyfonction à 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 keyqu'une seule fois sur chaque élément donc sera bien défini).
torek
2
@torek: Python utilise decorate-sort-undecorate lors du tri avec un keyappelable. Donc oui, c'est garanti car chaque valeur reçoit sa clé aléatoire exactement une fois.
Martijn Pieters
35
Cette méthode fonctionne aussi.
import random
shuffled = random.sample(original, len(original))
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']
shufflemodifie 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.
2. Style pythonique
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.
Mais je n'aime pas ça comme ça!
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.
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.
Réponses:
random.shuffle()
modifie lax
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()
avecrandom.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']
la source
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'appliquerkey
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.Cette méthode fonctionne aussi.
import random shuffled = random.sample(original, len(original))
la source
Selon la documentation :
>>> x = ['foo','bar','black','sheep'] >>> from random import shuffle >>> shuffle(x) >>> x ['bar', 'black', 'sheep', 'foo']
la source
Pourquoi, vraiment?
1. Efficacité
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.2. Style pythonique
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.
Mais je n'aime pas ça comme ça!
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
(voirsorted
) qui renvoienew_x
.la source
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']
la source
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]
la source
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]
la source