Random.shuffle neden Yok döndürüyor?


90

Python'da neden random.shufflegeri dönüyor None?

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> print shuffle(x)
None

Yerine karıştırılmış değeri nasıl elde ederim None?


rastgele bir değer değil, listenin rastgele karıştırılması.
alvas


Yanıtlar:


162

random.shuffle()değiştiren xlisteyi yerinde .

Yerinde bir yapıyı değiştiren Python API yöntemleri, değiştirilmiş Noneveri yapısını değil, genellikle döndürür .

Mevcut listenin düzenli tutulduğu mevcut bir listeye dayalı olarak rastgele karıştırılmış yeni bir liste oluşturmak isterseniz random.sample(), girdinin tam uzunluğu ile kullanabilirsiniz :

x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))     

Ayrıca kullanabilirsiniz sorted()ile random.random()bir sıralama anahtarı için:

shuffled = sorted(x, key=lambda k: random.random())

ancak bu, sıralamayı (bir O (NlogN) işlemi) çağırırken, giriş uzunluğuna örnekleme yalnızca O (N) işlemlerini alır ( random.shuffle()kullanılan işlemin aynısı , daralan bir havuzdan rasgele değerleri değiştirerek).

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']

2
Rastgele değerli bir keyişlev kullanmak gerçekten garanti ediliyor mu? Karşılaştırmalar kendiliğinden tutarlı değilse bazı hızlı sıralama algoritmaları başarısız olur. Bunun uygulamaya bağlı olarak her iki şekilde de çalıştığını görebiliyorum (dekore et-sırala-undecorate keyher öğeye yalnızca bir kez uygulanması gerektiğinden iyi tanımlanmış olacaktır).
torek

2
@torek: Python, bir keyçağrılabilir ile sıralarken dekorasyon-sırala-süslemesini kullanır . Yani evet, her bir değere rastgele anahtarları tam olarak bir kez verildiği için garantilidir.
Martijn Pieters

37

Bu yöntem de işe yarıyor.

import random
shuffled = random.sample(original, len(original))

8

Dokümanlara göre :

X dizisini yerinde karıştırın. İsteğe bağlı rastgele argüman, [0.0, 1.0) 'da rastgele bir kayan nokta döndüren bir 0 bağımsız değişken işlevidir; varsayılan olarak bu, random () işlevidir.

>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']

6

Neden, gerçekten mi?

1. Verimlilik

shufflelisteyi yerinde değiştirir. Bu güzel, çünkü artık orijinal listeye ihtiyacınız yoksa, büyük bir listenin kopyalanması tamamen ek yük olacaktır.

2. Pythonic stili

Göre "açık örtük daha iyidir" prensibi pythonic tarzı sonra kimse düşünebilir çünkü listesini dönen, kötü bir fikir olacağını, olduğunu aslında olmamasına rağmen bir yenisi.

Ama bundan hoşlanmadım!

Eğer varsa do taze listesi gerekir, gibi bir şey yazmak zorunda kalacak

new_x = list(x)  # make a copy
random.shuffle(new_x)

ki bu çok açık. Bu deyime sık sık ihtiyaç duyuyorsanız, onu geri dönen bir fonksiyona shuffled(bakınız sorted) sarın new_x.


2

Bu konseptle şöyle bir anım oldu:

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, referansla geçiş =) yerine varsayılan olarak "değerlere göre kopyala" yaptığı için stackoverflow.com/a/986495/610569
alvas

2

Yapıyı yerinde değiştiren Python API'leri , çıktı olarak None döndürür .

list = [1,2,3,4,5,6,7,8]
print(list)

Çıktı: [1, 2, 3, 4, 5, 6, 7, 8]

from random import shuffle
print(shuffle(list))

Çıktı: Yok

from random import sample
print(sample(list, len(list)))

Çıktı: [7, 3, 2, 4, 5, 6, 1, 8]


0

Karıştırılmış listeyi random.sample()başkaları tarafından açıklandığı gibi kullanarak geri verebilirsiniz . Listeden k elemanı değiştirmeden örnekleyerek çalışır . Dolayısıyla, listenizde yinelenen öğeler varsa, benzersiz şekilde ele alınacaktır.

>>> 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]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.