Los métodos de la API de Python que alteran una estructura en el lugar generalmente devuelven None, no la estructura de datos modificada.
Si desea crear una nueva lista aleatoria basada en una existente, donde la lista existente se mantiene en orden, puede usar random.sample()con la longitud completa de la entrada:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
pero esto invoca la clasificación (una operación O (NlogN)), mientras que el muestreo a la longitud de entrada solo toma operaciones O (N) (el mismo proceso que random.shuffle()se usa, intercambiando valores aleatorios de un grupo que se reduce).
¿Está keyrealmente garantizado el uso de una función de valor aleatorio ? Algunos algoritmos de clasificación rápida fracasan si las comparaciones no son autoconsistentes. Puedo ver que esto funciona de cualquier manera, dependiendo de la implementación (decorate-sort-undecorate solo deberá aplicarse keyuna vez en cada elemento, por lo que estará bien definido).
torek
2
@torek: Python usa decorate-sort-undecorate al ordenar con un keyinvocable. Así que sí, está garantizado ya que a cada valor se le da su clave aleatoria exactamente una vez.
Martijn Pieters
35
Este método también funciona.
import random
shuffled = random.sample(original, len(original))
Mezcla la secuencia x en su lugar. El argumento opcional aleatorio es una función de argumento 0 que devuelve un flotante aleatorio en [0.0, 1.0); por defecto, esta es la función aleatoria ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shufflemodifica la lista en su lugar. Esto es bueno, porque copiar una lista grande sería una sobrecarga si ya no necesita la lista original.
2. Estilo pitónico
Según el principio "explícito es mejor que implícito" del estilo pitónico , devolver la lista sería una mala idea, porque entonces se podría pensar que es nueva aunque en realidad no lo es.
¡Pero no me gusta así!
Si usted no necesita una nueva lista, tendrá que escribir algo como
new_x = list(x) # make a copy
random.shuffle(new_x)
que es muy explícito. Si necesita este modismo con frecuencia, envuélvalo en una función shuffled(ver sorted) que devuelva new_x.
Puede devolver la lista aleatoria utilizando random.sample()como explicaron otros. Funciona muestreando k elementos de la lista sin reemplazo . Entonces, si hay elementos duplicados en su lista, se tratarán de manera única.
Respuestas:
random.shuffle()
cambia lax
lista en su lugar .Los métodos de la API de Python que alteran una estructura en el lugar generalmente devuelven
None
, no la estructura de datos modificada.Si desea crear una nueva lista aleatoria basada en una existente, donde la lista existente se mantiene en orden, puede usar
random.sample()
con la longitud completa de la entrada:x = ['foo', 'bar', 'black', 'sheep'] random.sample(x, len(x))
También puede usar
sorted()
conrandom.random()
para una clave de clasificación:shuffled = sorted(x, key=lambda k: random.random())
pero esto invoca la clasificación (una operación O (NlogN)), mientras que el muestreo a la longitud de entrada solo toma operaciones O (N) (el mismo proceso que
random.shuffle()
se usa, intercambiando valores aleatorios de un grupo que se reduce).Manifestación:
>>> 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']
fuente
key
realmente garantizado el uso de una función de valor aleatorio ? Algunos algoritmos de clasificación rápida fracasan si las comparaciones no son autoconsistentes. Puedo ver que esto funciona de cualquier manera, dependiendo de la implementación (decorate-sort-undecorate solo deberá aplicarsekey
una vez en cada elemento, por lo que estará bien definido).key
invocable. Así que sí, está garantizado ya que a cada valor se le da su clave aleatoria exactamente una vez.Este método también funciona.
import random shuffled = random.sample(original, len(original))
fuente
Según los documentos :
>>> x = ['foo','bar','black','sheep'] >>> from random import shuffle >>> shuffle(x) >>> x ['bar', 'black', 'sheep', 'foo']
fuente
¿Por qué realmente?
1. Eficiencia
shuffle
modifica la lista en su lugar. Esto es bueno, porque copiar una lista grande sería una sobrecarga si ya no necesita la lista original.2. Estilo pitónico
Según el principio "explícito es mejor que implícito" del estilo pitónico , devolver la lista sería una mala idea, porque entonces se podría pensar que es nueva aunque en realidad no lo es.
¡Pero no me gusta así!
Si usted no necesita una nueva lista, tendrá que escribir algo como
new_x = list(x) # make a copy random.shuffle(new_x)
que es muy explícito. Si necesita este modismo con frecuencia, envuélvalo en una función
shuffled
(versorted
) que devuelvanew_x
.fuente
Tuve mi momento aha con este concepto como este:
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']
fuente
Las API de Python que cambian la estructura en su lugar devuelven None como resultado.
list = [1,2,3,4,5,6,7,8] print(list)
Salida: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle print(shuffle(list))
Salida: ninguna
from random import sample print(sample(list, len(list)))
Salida: [7, 3, 2, 4, 5, 6, 1, 8]
fuente
Puede devolver la lista aleatoria utilizando
random.sample()
como explicaron otros. Funciona muestreando k elementos de la lista sin reemplazo . Entonces, si hay elementos duplicados en su lista, se tratarán de manera única.>>> 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]
fuente