Warum random.shuffle
kehrt man None
in Python zurück?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Wie erhalte ich den gemischten Wert anstelle von None
?
Warum random.shuffle
kehrt man None
in Python zurück?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Wie erhalte ich den gemischten Wert anstelle von None
?
Antworten:
random.shuffle()
ändert die x
Liste an Ort und Stelle .
Python-API-Methoden, die eine Struktur direkt ändern, geben im Allgemeinen None
nicht die geänderte Datenstruktur zurück.
Wenn Sie eine neue zufällig gemischte Liste basierend auf einer vorhandenen Liste erstellen möchten, in der die vorhandene Liste in der richtigen Reihenfolge gehalten wird, können Sie sie random.sample()
mit der gesamten Länge der Eingabe verwenden:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
Sie können auch sorted()
mit random.random()
für einen Sortierschlüssel verwenden:
shuffled = sorted(x, key=lambda k: random.random())
Dies ruft jedoch die Sortierung auf (eine O (NlogN) -Operation), während das Abtasten auf die Eingabelänge nur O (N) -Operationen erfordert (der gleiche Prozess wie random.shuffle()
der, bei dem zufällige Werte aus einem schrumpfenden Pool ausgetauscht werden).
Demo:
>>> 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
Funktion wirklich garantiert? Einige schnelle Sortieralgorithmen fallen um, wenn Vergleiche nicht selbstkonsistent sind. Ich kann sehen, dass dies je nach Implementierung in beide Richtungen funktioniert (Decorate-Sort-Undecorate muss nur key
einmal auf jedes Element angewendet werden, damit es genau definiert ist).
key
aufrufbaren Element dekorieren-sortieren-undekorieren . Also ja, es ist garantiert, da jeder Wert genau einmal seinen Zufallsschlüssel erhält.
Laut Dokumentation :
Mische die Sequenz x an Ort und Stelle. Das optionale Argument random ist eine 0-Argument-Funktion, die einen zufälligen Float in [0.0, 1.0) zurückgibt. Standardmäßig ist dies die Funktion random ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffle
ändert die Liste an Ort und Stelle. Das ist schön, denn das Kopieren einer großen Liste wäre ein reiner Aufwand, wenn Sie die ursprüngliche Liste nicht mehr benötigen.
Nach dem Prinzip "explizit ist besser als implizit" des pythonischen Stils wäre es eine schlechte Idee, die Liste zurückzugeben, da man dann denken könnte, es sei eine neue, obwohl dies tatsächlich nicht der Fall ist.
Wenn Sie noch eine frische Liste benötigen, haben Sie so etwas wie schreiben
new_x = list(x) # make a copy
random.shuffle(new_x)
das ist schön explizit. Wenn Sie dieses Idiom häufig benötigen, schließen Sie es in eine Funktion shuffled
(siehe sorted
) ein, die zurückgibt new_x
.
Ich hatte meinen Aha-Moment mit diesem Konzept wie folgt:
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-APIs, die die Struktur selbst ändern, geben None als Ausgabe zurück.
list = [1,2,3,4,5,6,7,8]
print(list)
Ausgabe: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle
print(shuffle(list))
Ausgabe: Keine
from random import sample
print(sample(list, len(list)))
Ausgabe: [7, 3, 2, 4, 5, 6, 1, 8]
Sie können die gemischte Liste random.sample()
wie von anderen erläutert zurückgeben. Es funktioniert, indem k Elemente aus der Liste ersatzlos abgetastet werden . Wenn Ihre Liste also doppelte Elemente enthält, werden diese eindeutig behandelt.
>>> 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]