2012-03-18 19 views
42

Intenté usar random.randint(0, 100), pero algunos números eran iguales. ¿Existe un método/módulo para crear una lista de números aleatorios únicos?¿Cómo creo una LISTA de números aleatorios únicos?

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); 
+7

Si son únicos, entonces no son realmente aleatorios. –

+1

@ IgnacioVazquez-Abrams Estoy tratando de implementar un método que mi profesor llamó "arranque", estamos haciendo una "investigación" en los motores de búsqueda. – iCodeLikeImDrunk

+0

@ IgnacioVazquez-Abrams lo son si representan selecciones aleatorias sin reemplazo. Esta es una pregunta sobre un lenguaje de programación de uso general ... * lo usamos * para cosas –

Respuesta

78

Esto devolverá una lista de 10 números seleccionados del rango de 0 a 99, sin duplicados.

random.sample(range(100), 10) 

Con referencia a su ejemplo de código específico, es probable que quieren leer todas las líneas del archivo una vez y luego seleccionar líneas al azar de la lista guardada en la memoria. Por ejemplo:

all_lines = f1.readlines() 
for i in range(50): 
    lines = random.sample(all_lines, 40) 

De esta manera, solo necesita leer el archivo una vez antes de su ciclo. Es mucho más eficiente hacer esto que buscar nuevamente el inicio del archivo y llamar de nuevo al f1.readlines() para cada iteración de bucle.

+0

También probé esto, lines = random.sample (f1.readlines(), 40); me sigue dando la "muestra más grande que la población" cuando traté de ejecutarla a través de un bucle for ... ¿Algún consejo? – iCodeLikeImDrunk

+1

Su fuente contiene menos de 40 líneas, por lo que 'random.sample()' no puede darle una lista de 40 líneas sin duplicados. –

+0

La lista de llamadas no es necesaria, creo (tanto para 2 como para 3). – DSM

3

Si la lista de N números de 1 a N se genera aleatoriamente, entonces sí, existe la posibilidad de que algunos números se repitan.

Si desea una lista de números de 1 a N en orden aleatorio, llene una matriz con inegeters 1 a N, y luego use Fisher-Yates shuffle.

actualización: como señala @ Greg: puesto que se trata de Python, utilice random.shuffle()

7

Por qué no crear una lista de 1..100 y mezclar con Fisher-Yates algoritmo?

+15

o, como esto es Python, 'random.shuffle()' ... –

+3

a veces ser primero no es suficiente ... :) –

1

Si desea asegurarse de que los números que se agregan son únicos, se puede utilizar un Set object

si se utiliza 2,7 o mayor, o importar los conjuntos de módulo si no.

Como han mencionado otros, esto significa que los números no son realmente aleatorios.

6

Greg Hewgill funciona (+1), pero podría ser problemático 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 corregir esto, me gustaría ir con esto:

answer = set() 
sampleSize = 10 
answerSize = 0 

while answerSize < sampleSize: 
    r = random.randint(0,100) 
    if r not in answer: 
     answerSize += 1 
     answer.add(r) 
# answer now contains 10 unique, random integers from 0.. 100 
4

Puede utilizar el ordenar de forma aleatoria función del módulo de random así:

import random 

my_list = list(xrange(1,100)) # list of integers from 1 to 99 
           # adjust this boundaries to fit your needs 
random.shuffle(my_list) 
print my_list # <- List of unique random numbers 

señalar aquí que el método aleatorio doesn 'Devuelve cualquier lista como uno puede esperar, solo mezcla la lista pasada por referencia.

0

desde la CLI en Win XP:

python -c "import random; print(sorted(set([random.randint(6,49) for i in range(7)]))[:6])" 

En Canadá tenemos la Lotto 6/49. Acabo de envolver el código anterior en lotto.bat y ejecuto C:\home\lotto.bat o simplemente C:\home\lotto.

Debido random.randint a menudo se repite un número, utilizo set con range(7) y luego acortarlo a una longitud de 6.

ocasionalmente si un número se repite más de 2 veces la longitud de la lista resultante será menor que 6.

EDITAR: Sin embargo, random.sample(range(6,49),6) es la forma correcta de hacerlo.

0

import random result=[] for i in range(1,50): rng=random.randint(1,20) result.append(rng)

2

Si necesita muestrear un número extremadamente grande, no se puede utilizar range

random.sample(range(10000000000000000000000000000000), 10) 

porque arroja:

OverflowError: Python int too large to convert to C ssize_t 

Además, si random.sample no puede producir el número de elementos que desea debido a que el rango es demasiado pequeño

random.sample(range(2), 1000) 

arroja:

ValueError: Sample larger than population 

Esta función se resuelve ambos problemas:

import random 

def random_sample(count, start, stop, step=1): 
    def gen_random(): 
     while True: 
      yield random.randrange(start, stop, step) 

    def gen_n_unique(source, n): 
     seen = set() 
     seenadd = seen.add 
     for i in (i for i in source() if i not in seen and not seenadd(i)): 
      yield i 
      if len(seen) == n: 
       break 

    return [i for i in gen_n_unique(gen_random, 
            min(count, int(abs(stop - start)/abs(step))))] 

uso con un número extremadamente grande:

print('\n'.join(map(str, random_sample(10, 2, 10000000000000000000000000000000)))) 

resultado de la muestra:

7822019936001013053229712669368 
6289033704329783896566642145909 
2473484300603494430244265004275 
5842266362922067540967510912174 
6775107889200427514968714189847 
9674137095837778645652621150351 
9969632214348349234653730196586 
1397846105816635294077965449171 
3911263633583030536971422042360 
9864578596169364050929858013943 

Uso donde el rango es menor que el número de artículos solicitados: resultado

print(', '.join(map(str, random_sample(100000, 0, 3)))) 

muestra:

2, 0, 1 

También funciona con con rangos negativos y pasos:

print(', '.join(map(str, random_sample(10, 10, -10, -2)))) 
print(', '.join(map(str, random_sample(10, 5, -5, -2)))) 

de ejemplo resultados:

2, -8, 6, -2, -4, 0, 4, 10, -6, 8 
-3, 1, 5, -1, 3 
1

Puede utilizar biblioteca Numpy de respuesta rápida como se muestra a continuación -

listas fragmento de código dado un 6 únicas números entre el rango de 0 a 5. Puede ajustar los parámetros para su comodidad.

import numpy as np 
import random 
a = np.linspace(0, 5, 6) 
random.shuffle(a) 
print(a) 

salida

[ 2. 1. 5. 3. 4. 0.] 

No pone ninguna restricción como vemos en random.sample que se refiere here.

Espero que esto ayude un poco.

Cuestiones relacionadas