Perché random.shuffle
ritorna None
in Python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Come ottengo il valore mescolato invece di None
?
Perché random.shuffle
ritorna None
in Python?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Come ottengo il valore mescolato invece di None
?
Risposte:
random.shuffle()
cambia l' x
elenco in posizione .
I metodi API Python che alterano una struttura sul posto generalmente restituiscono None
, non la struttura dei dati modificata.
Se si desidera creare un nuovo elenco mescolato in modo casuale basato su uno esistente, in cui l'elenco esistente viene mantenuto in ordine, è possibile utilizzare random.sample()
con l'intera lunghezza dell'input:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
Puoi anche usare sorted()
con random.random()
per una chiave di ordinamento:
shuffled = sorted(x, key=lambda k: random.random())
ma questo richiama l'ordinamento (un'operazione O (NlogN)), mentre il campionamento alla lunghezza di input richiede solo operazioni O (N) (lo stesso processo random.shuffle()
utilizzato, scambiando valori casuali da un pool di riduzione).
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
funzione a valori casuali è davvero garantito? Alcuni algoritmi di ordinamento rapido cadono se i confronti non sono auto-coerenti. Posso vedere che funziona in entrambi i modi, a seconda dell'implementazione (decor-sort-undecorate dovrà essere applicato solo key
una volta su ogni elemento, quindi sarà ben definito).
key
callable. Quindi sì, è garantito poiché a ciascun valore viene assegnata la chiave casuale esattamente una volta.
Secondo i documenti :
Mescola la sequenza x in posizione. L'argomento opzionale random è una funzione con 0 argomenti che restituisce un float casuale in [0.0, 1.0); per impostazione predefinita, questa è la funzione random ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffle
modifica l'elenco in atto. Questo è bello, perché copiare un elenco di grandi dimensioni sarebbe un puro sovraccarico se non hai più bisogno dell'elenco originale.
Secondo il principio "esplicito è meglio che implicito" dello stile pitonico , restituire l'elenco sarebbe una cattiva idea, perché allora si potrebbe pensare che sia nuovo, anche se in realtà non lo è.
Se non bisogno di una lista fresca, si dovrà scrivere qualcosa di simile
new_x = list(x) # make a copy
random.shuffle(new_x)
che è piacevolmente esplicito. Se hai bisogno di questo idioma frequentemente, racchiudilo in una funzione shuffled
(vedi sorted
) che restituisce new_x
.
Ho avuto il mio aha momento con questo concetto in questo modo:
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']
Le API Python che modificano la struttura in posizione restituiscono None come output.
list = [1,2,3,4,5,6,7,8]
print(list)
Uscita: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle
print(shuffle(list))
Uscita: nessuno
from random import sample
print(sample(list, len(list)))
Uscita: [7, 3, 2, 4, 5, 6, 1, 8]
È possibile restituire l'elenco mescolato utilizzando random.sample()
come spiegato da altri. Funziona campionando k elementi dall'elenco senza sostituzione . Pertanto, se nell'elenco sono presenti elementi duplicati, verranno trattati in modo univoco.
>>> 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]