Intenté usar random.randint(0, 100)
, pero algunos números eran los mismos. ¿Existe un método / módulo para crear una lista de números aleatorios únicos?
Nota: El siguiente código se basa en una respuesta y se agregó después de que se publicó la respuesta. No es parte de la pregunta; es la solucion.
def getScores():
# open files to read and write
f1 = open("page.txt", "r");
p1 = open("pgRes.txt", "a");
gScores = [];
bScores = [];
yScores = [];
# run 50 tests of 40 random queries to implement "bootstrapping" method
for i in range(50):
# get 40 random queries from the 50
lines = random.sample(f1.readlines(), 40);
Respuestas:
Esto devolverá una lista de 10 números seleccionados del rango de 0 a 99, sin duplicados.
Con referencia a su ejemplo de código específico, probablemente desee leer todas las líneas del archivo una vez y luego seleccionar líneas aleatorias de la lista guardada en la memoria. Por ejemplo:
De esta manera, solo necesita leer el archivo una vez, antes de su ciclo. Es mucho más eficiente hacer esto que volver al inicio del archivo y
f1.readlines()
volver a llamar para cada iteración del ciclo.fuente
Puede usar la función de reproducción aleatoria del módulo aleatorio de esta manera:
Tenga en cuenta aquí que el método shuffle no devuelve ninguna lista como cabría esperar, solo baraja la lista pasada por referencia.
fuente
Primero puede crear una lista de números desde
a
hastab
, dondea
yb
son respectivamente los números más pequeños y más grandes en su lista, luego mezclarlos con el algoritmo de Fisher-Yates o usando elrandom.shuffle
método de Python .fuente
La solución presentada en esta respuesta funciona, pero podría volverse problemática con la memoria si el tamaño de la muestra es pequeño, pero la población es enorme (por ejemplo
random.sample(insanelyLargeNumber, 10)
).Para arreglar eso, iría con esto:
fuente
random.sample
usa este enfoque para una pequeña cantidad de muestras de una gran población, por lo que este problema con la memoria ya no existe. Aunque, en el momento en que se escribió esta respuesta, la implementación derandom.shuffle
puede haber sido diferente.Generador de números pseudoaleatorios congruentes lineales
Este problema se puede resolver con un simple generador de congruencia lineal . Esto requiere una sobrecarga de memoria constante (8 enteros) y como máximo 2 * cálculos (longitud de secuencia).
Todas las demás soluciones usan más memoria y más computación. Si solo necesita unas pocas secuencias aleatorias, este método será significativamente más económico. Para rangos de tamaño
N
, si desea generar en el orden de secuenciasN
únicask
o más, recomiendo la solución aceptada utilizando los métodos incorporados,random.sample(range(N),k)
ya que se ha optimizado en Python para la velocidad.Código
Uso
El uso de esta función "rango_aleatorio" es el mismo que para cualquier generador (como "rango"). Un ejemplo:
Resultados de muestra
fuente
prime
, la función solo me devolverá 4 respuestas posibles, porquevalue
es la única cosa elegida al azar con 4 valores posibles, cuando necesitamos al menos (4 elegir 2) = 6, (permitiendo un orden no aleatorio).random_range(2,4)
devolverá los valores {(1, 0), (3, 2), (2, 1), (0, 3)}, pero nunca el par (3,1) (o (1,3)). ¿Está esperando nuevos números primos grandes generados aleatoriamente en cada llamada de función?random_range(v)
regresa av
secuencias únicas en lugar dev!
)Si la lista de N números del 1 al N se genera aleatoriamente, entonces sí, existe la posibilidad de que algunos números se repitan.
Si desea una lista de números del 1 al N en un orden aleatorio, complete una matriz con números enteros del 1 al N y luego use una combinación de Fisher-Yates o Python
random.shuffle()
.fuente
Si necesita muestrear números extremadamente grandes, no puede usar
range
porque arroja:
Además, si
random.sample
no puede producir la cantidad de elementos que desea debido a que el rango es demasiado pequeñoarroja:
Esta función resuelve ambos problemas:
Uso con números extremadamente grandes:
Resultado de la muestra:
Uso donde el rango es menor que el número de elementos solicitados:
Resultado de la muestra:
También funciona con rangos y pasos negativos:
Resultados de muestra:
fuente
Puede usar la biblioteca Numpy para una respuesta rápida como se muestra a continuación:
El fragmento de código dado enumera 6 números únicos entre el rango de 0 a 5. Puede ajustar los parámetros para su comodidad.
Salida
No impone ninguna restricción como vemos en random.sample como se hace referencia aquí .
Espero que esto ayude un poco.
fuente
La respuesta proporcionada aquí funciona muy bien con respecto al tiempo y a la memoria, pero un poco más complicada ya que utiliza construcciones de Python avanzadas como yield. La respuesta más simple funciona bien en la práctica, pero el problema con esa respuesta es que puede generar muchos números enteros falsos antes de construir el conjunto requerido. Pruébelo con PopulationSize = 1000, sampleSize = 999. En teoría, existe la posibilidad de que no termine.
La respuesta a continuación aborda ambos problemas, ya que es determinista y algo eficiente, aunque actualmente no es tan eficiente como los otros dos.
donde las funciones getElem, percolateUp son las que se definen a continuación
Finalmente, el tiempo en promedio fue de aproximadamente 15 ms para un valor grande de n como se muestra a continuación,
fuente
random.randint
función 3996 veces, mientras que la otra cca. 6000 veces. No es una gran mejora, ¿eh?Para obtener un programa que genere una lista de valores aleatorios sin duplicados que sea determinista, eficiente y construido con construcciones de programación básicas, considere la función
extractSamples
definida a continuación,La idea básica es realizar un seguimiento de los intervalos
intervalLst
de posibles valores entre los que seleccionar nuestros elementos requeridos. Esto es determinista en el sentido de que tenemos la garantía de generar una muestra dentro de un número fijo de pasos (dependiente únicamente depopulationSize
ysampleSize
).Para usar la función anterior para generar nuestra lista requerida,
También podemos comparar con una solución anterior (para un valor más bajo de PopulationSize)
Tenga en cuenta que reduje el
populationSize
valor ya que produce un error de memoria para valores más altos al usar larandom.sample
solución (también mencionado en las respuestas anteriores aquí y aquí ). Para los valores anteriores, también podemos observar queextractSamples
supera elrandom.sample
enfoque.PD: Aunque el enfoque principal es similar a mi respuesta anterior , hay modificaciones sustanciales en la implementación, así como en el enfoque junto con una mejora en la claridad.
fuente
Una función muy sencilla que también resuelve tu problema
fuente
El problema con los enfoques basados en conjuntos ("si hay un valor aleatorio en los valores devueltos, inténtalo de nuevo") es que su tiempo de ejecución no está determinado debido a las colisiones (que requieren otra iteración de "intentar de nuevo"), especialmente cuando se devuelve una gran cantidad de valores aleatorios. de la gama.
Una alternativa que no es propensa a este tiempo de ejecución no determinista es la siguiente:
fuente
fuente
Si desea asegurarse de que los números que se agregan sean únicos, puede usar un objeto Set
si usa 2.7 o superior, o importe el módulo de conjuntos si no.
Como han mencionado otros, esto significa que los números no son verdaderamente aleatorios.
fuente
para muestrear enteros sin reemplazo entre
minval
ymaxval
:con jax:
fuente
n_samples
de ellos? ¿Cuál es su razonamiento detrás de este enfoque? ¿Puede explicar cuáles son las ventajas de su enfoque, en comparación con cualquiera de la gran cantidad de respuestas existentes (la mayoría de hace 8 años)?random.shuffle
, utilizan Mersenne Twister, que es mucho más lento que los algoritmos ofrecidos por numpy (y probablemente jax). numpy y jax permiten otros algoritmos de generación de números aleatorios. jax también permite la compilación jit y la diferenciación, lo que puede ser útil para la diferenciación estocástica. Además, con respecto a una matriz "posiblemente grande", algunas de las respuestas más votadas hacen exactamente lo mismorandom.shuffle
, lo que no creo que sea pecaminoso en un sentido relativo o incluso absolutorandom.shuffle
usa Mersenne Twister": es la mezcla de Fisher-Yates, como se menciona en varias respuestas. Tiene una complejidad de tiempo lineal, por lo que no puede ser asintóticamente más lento que los algoritmos ofrecidos por cualquier otra biblioteca, ya sea numérica o de otro tipo. Si numpy es más rápido, es solo porque está implementado en C, pero esto no justifica generar una gran permutación (una que ni siquiera cabe en la memoria), solo para elegir algunos elementos de ella. No hay una sola respuesta además de la tuya que haga esto.random
módulo está escrito en Python, por lo que puede ver fácilmente su fuente (probarrandom.__file__
).Desde la CLI en win xp:
En Canadá tenemos la lotería 6/49. Simplemente envuelvo el código anterior en lotto.bat y ejecuto
C:\home\lotto.bat
o simplementeC:\home\lotto
.Debido a que a
random.randint
menudo repite un número, lo usoset
conrange(7)
y luego lo acorto a una longitud de 6.Ocasionalmente, si un número se repite más de 2 veces, la longitud de la lista resultante será inferior a 6.
EDITAR: Sin embargo,
random.sample(range(6,49),6)
es el camino correcto a seguir.fuente
fuente
print len(result), len(set(result))
. Es de esperar queresult
tenga elementos únicos solo una vez en cada1.0851831788708547256608362340568947172111832359638926... × 10^20
intento.