Dlaczego random.shuffle
powraca None
w Pythonie?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Jak uzyskać przetasowaną wartość zamiast None
?
Dlaczego random.shuffle
powraca None
w Pythonie?
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None
Jak uzyskać przetasowaną wartość zamiast None
?
Odpowiedzi:
random.shuffle()
zmienia x
listę na miejscu .
Metody interfejsu API języka Python, które zmieniają strukturę lokalnie, generalnie zwracają None
, a nie zmodyfikowaną strukturę danych.
Jeśli chcesz utworzyć nową losowo odtwarzaną listę na podstawie istniejącej, gdzie istniejąca lista jest utrzymywana w porządku, możesz użyć random.sample()
z pełną długością danych wejściowych:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
Możesz również użyć sorted()
z random.random()
jako klucz sortowania:
shuffled = sorted(x, key=lambda k: random.random())
ale to wywołuje sortowanie (operacja O (NlogN)), podczas gdy próbkowanie do długości wejściowej wymaga tylko operacji O (N) (ten sam proces, który random.shuffle()
jest używany, zastępując losowe wartości z kurczącej się puli).
Próbny:
>>> 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
funkcji o wartości losowej jest naprawdę gwarantowane? Niektóre algorytmy szybkiego sortowania zawodzą, jeśli porównania nie są spójne. Widzę, że działa to w obie strony, w zależności od implementacji (dekorowanie-sortowanie-undecorate będzie musiało zostać zastosowane key
tylko raz na każdym elemencie, więc będzie dobrze zdefiniowane).
key
wywołania. Więc tak, jest to gwarantowane, ponieważ każda wartość otrzymuje swój losowy klucz dokładnie raz.
Według dokumentów :
Potasuj sekwencję x na miejscu. Opcjonalny argument random to 0-argumentowa funkcja zwracająca losową liczbę zmiennoprzecinkową z wartości [0.0, 1.0); domyślnie jest to funkcja random ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffle
modyfikuje listę w miejscu. To jest miłe, ponieważ kopiowanie dużej listy byłoby czystym kosztem, jeśli nie potrzebujesz już oryginalnej listy.
Zgodnie z zasadą stylu pythonowego „wyraźne jest lepsze niż niejawne” , zwrócenie listy byłoby złym pomysłem, ponieważ wówczas można by pomyśleć, że jest to nowa, chociaż w rzeczywistości tak nie jest.
Jeśli nie potrzebujesz nową listę, trzeba będzie napisać coś podobnego
new_x = list(x) # make a copy
random.shuffle(new_x)
co jest ładnie wyraźne. Jeśli często potrzebujesz tego idiomu, zawiń go w funkcję shuffled
(zobacz sorted
), która zwraca new_x
.
Miałem chwilę aha z taką koncepcją:
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']
Pythonowe API, które zmieniają strukturę, same zwracają None jako dane wyjściowe.
list = [1,2,3,4,5,6,7,8]
print(list)
Wyjście: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle
print(shuffle(list))
Wyjście: brak
from random import sample
print(sample(list, len(list)))
Wyjście: [7, 3, 2, 4, 5, 6, 1, 8]
Możesz zwrócić potasowaną listę, korzystając z random.sample()
wyjaśnień innych. Działa na zasadzie próbkowania k elementów z listy bez zastępowania . Jeśli więc na liście znajdują się zduplikowane elementy, zostaną one potraktowane wyjątkowo.
>>> 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]