Os métodos da API Python que alteram uma estrutura local geralmente retornam None, não a estrutura de dados modificada.
Se você quiser criar uma nova lista embaralhada aleatoriamente com base em uma existente, em que a lista existente é mantida em ordem, você pode usar random.sample()com o comprimento total da entrada:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
mas isso invoca a classificação (uma operação O (NlogN)), enquanto a amostragem para o comprimento de entrada leva apenas O (N) operações (o mesmo processo que random.shuffle()é usado, trocando valores aleatórios de um pool de encolhimento).
O uso de uma keyfunção com valor aleatório é realmente garantido? Alguns algoritmos de classificação rápida falham se as comparações não forem autoconsistentes. Eu posso ver isso funcionando de qualquer maneira, dependendo da implementação (decorate-sort-undecorate só precisará ser aplicado keyuma vez em cada elemento, portanto, será bem definido).
Torek
2
@torek: Python usa decorate-sort-undecorate ao classificar com um keychamável. Portanto, sim, é garantido que cada valor recebe sua chave aleatória exatamente uma vez.
Martijn Pieters
35
Este método também funciona.
import random
shuffled = random.sample(original, len(original))
Embaralhe a sequência x no lugar. O argumento opcional random é uma função de 0 argumento que retorna um float aleatório em [0.0, 1.0); por padrão, esta é a função random ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shufflemodifica a lista no local. Isso é bom, porque copiar uma lista grande seria pura sobrecarga se você não precisar mais da lista original.
2. Estilo pitônico
De acordo com o princípio "explícito é melhor do que implícito" do estilo pythônico , devolver a lista seria uma má ideia, porque então poderíamos pensar que é uma lista nova, embora na verdade não seja.
Mas eu não gosto assim!
Se você não precisa de uma nova lista, você terá que escrever algo como
new_x = list(x) # make a copy
random.shuffle(new_x)
o que é bem explícito. Se você precisa desse idioma com freqüência, envolva-o em uma função shuffled(consulte sortedRecursos) que retorna new_x.
Você pode retornar a lista embaralhada usando random.sample()conforme explicado por outros. Ele funciona por amostragem de k elementos da lista sem substituição . Portanto, se houver elementos duplicados em sua lista, eles serão tratados de forma exclusiva.
Respostas:
random.shuffle()
muda ax
lista no local .Os métodos da API Python que alteram uma estrutura local geralmente retornam
None
, não a estrutura de dados modificada.Se você quiser criar uma nova lista embaralhada aleatoriamente com base em uma existente, em que a lista existente é mantida em ordem, você pode usar
random.sample()
com o comprimento total da entrada:x = ['foo', 'bar', 'black', 'sheep'] random.sample(x, len(x))
Você também pode usar
sorted()
comrandom.random()
para uma chave de classificação:shuffled = sorted(x, key=lambda k: random.random())
mas isso invoca a classificação (uma operação O (NlogN)), enquanto a amostragem para o comprimento de entrada leva apenas O (N) operações (o mesmo processo que
random.shuffle()
é usado, trocando valores aleatórios de um pool de encolhimento).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']
fonte
key
função com valor aleatório é realmente garantido? Alguns algoritmos de classificação rápida falham se as comparações não forem autoconsistentes. Eu posso ver isso funcionando de qualquer maneira, dependendo da implementação (decorate-sort-undecorate só precisará ser aplicadokey
uma vez em cada elemento, portanto, será bem definido).key
chamável. Portanto, sim, é garantido que cada valor recebe sua chave aleatória exatamente uma vez.Este método também funciona.
import random shuffled = random.sample(original, len(original))
fonte
De acordo com a documentação :
>>> x = ['foo','bar','black','sheep'] >>> from random import shuffle >>> shuffle(x) >>> x ['bar', 'black', 'sheep', 'foo']
fonte
Por que, realmente?
1. Eficiência
shuffle
modifica a lista no local. Isso é bom, porque copiar uma lista grande seria pura sobrecarga se você não precisar mais da lista original.2. Estilo pitônico
De acordo com o princípio "explícito é melhor do que implícito" do estilo pythônico , devolver a lista seria uma má ideia, porque então poderíamos pensar que é uma lista nova, embora na verdade não seja.
Mas eu não gosto assim!
Se você não precisa de uma nova lista, você terá que escrever algo como
new_x = list(x) # make a copy random.shuffle(new_x)
o que é bem explícito. Se você precisa desse idioma com freqüência, envolva-o em uma função
shuffled
(consultesorted
Recursos) que retornanew_x
.fonte
Eu tive meu momento aha com este conceito assim:
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']
fonte
APIs Python que mudam a estrutura no local, retornam None como saída.
list = [1,2,3,4,5,6,7,8] print(list)
Resultado: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle print(shuffle(list))
Resultado: Nenhum
from random import sample print(sample(list, len(list)))
Resultado: [7, 3, 2, 4, 5, 6, 1, 8]
fonte
Você pode retornar a lista embaralhada usando
random.sample()
conforme explicado por outros. Ele funciona por amostragem de k elementos da lista sem substituição . Portanto, se houver elementos duplicados em sua lista, eles serão tratados de forma exclusiva.>>> 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]
fonte