2012-03-18 24 views
42

Próbowałem użyć random.randint(0, 100), ale niektóre liczby były takie same. Czy istnieje metoda/moduł do tworzenia listy unikalnych liczb losowych?Jak utworzyć listę unikatowych liczb losowych?

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

Jeśli są unikatowe, nie są przypadkowe. –

+1

@ IgnacioVazquez-Abrams próbuję wdrożyć metodę, którą mój prof nazwał "bootstrapping", robimy "badania" w wyszukiwarkach .. – iCodeLikeImDrunk

+0

@ IgnacioVazquez-Abrams są, jeśli reprezentują losowe selekcje bez wymiany. To jest pytanie dotyczące ogólnego języka programowania użytkowania ... używamy * go dla rzeczy –

Odpowiedz

78

Spowoduje to wyświetlenie listy 10 numerów wybranych z zakresu od 0 do 99 bez duplikatów.

random.sample(range(100), 10) 

Odnosząc się do konkretnego przykładu kodu, prawdopodobnie chcesz, aby przeczytać wszystkie wiersze z pliku raz a następnie wybrać losowo wiersze z listy zapisanej w pamięci. Na przykład:

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

ten sposób, trzeba tylko właściwie odczytać z pliku raz, przed pętlą. Jest to o wiele wydajniejsze niż odszukiwanie początku pliku i ponowne wywołanie f1.readlines() dla każdej iteracji pętli.

+0

Próbowałem również to, lines = random.sample (f1.readlines(), 40); nadal daje mi "próbkę większą niż populację", gdy próbowałem uruchomić ją przez pętlę for .. jakaś rada? – iCodeLikeImDrunk

+1

Twoje źródło zawiera mniej niż 40 wierszy, więc 'random.sample()' nie może wyświetlić listy 40 wierszy bez duplikatów. –

+0

Wywołanie listy jest niepotrzebne, myślę (dla obu 2 i 3). – DSM

3

Jeśli lista numerów N od 1 do N jest generowana losowo, to tak, istnieje możliwość, że niektóre liczby mogą się powtarzać.

Jeśli chcesz, aby lista liczb od 1 do N w kolejności losowej, wypełnij tablicę z inegeters 1 do N, a następnie użyj Fisher-Yates shuffle.

Aktualizacja: jak @Greg zaznacza: ponieważ jest Python, użyj random.shuffle()

7

Dlaczego nie stworzyć listę 1..100 i przetasować je Fisher-Yates algorytmu?

+15

lub, ponieważ jest to Python, 'random.shuffle()' ... –

+3

czasami bycie pierwszym nie wystarcza ... :) –

1

Jeśli chcesz upewnić się, że numery dodawane są wyjątkowe, można użyć Set object

przypadku korzystania z 2,7 lub większej, lub jeśli nie importować zestawy moduł.

Jak wspomnieli inni, oznacza to, że liczby nie są przypadkowe.

6

Greg Hewgill (+1), ale może to powodować problemy z pamięcią, jeśli wielkość próby jest niewielka, ale populacja jest ogromna (np. random.sample(insanelyLargeNumber, 10)).

Aby ustalić, że pójdę z tym:

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

Można użyć przetasować funkcji z modułu random tak:

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 

tu zauważyć, że metoda losowego nie robi nie zwraca żadnej listy, jak można się spodziewać, tylko przetasowuje listę przekazaną przez odniesienie.

0

Z CLI w Win XP:

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

W Kanadzie mamy 6/49 Lotto. Właśnie zapakuję powyższy kod w lotto.bat i uruchomię C:\home\lotto.bat lub po prostu C:\home\lotto.

Ponieważ random.randint często powtarza szereg używam set z range(7) a następnie ją skrócić do długości 6.

Czasami jeśli liczba powtarza się więcej niż 2 razy uzyskaną długość lista będzie mniej niż 6.

EDYCJA: Jednak, random.sample(range(6,49),6) jest prawidłowym sposobem postępowania.

0

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

2

Jeśli chcesz skosztować niezwykle dużych ilościach, nie można używać range

random.sample(range(10000000000000000000000000000000), 10) 

ponieważ rzuca:

OverflowError: Python int too large to convert to C ssize_t 

Ponadto, jeśli random.sample nie może produkować liczbę przedmiotów, które chcesz ze względu na zbyt mały zakres

random.sample(range(2), 1000) 

rzuca:

ValueError: Sample larger than population 

Funkcja ta rozwiązuje oba problemy:

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

Usage z bardzo dużych liczb:

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

wynik próbki:

7822019936001013053229712669368 
6289033704329783896566642145909 
2473484300603494430244265004275 
5842266362922067540967510912174 
6775107889200427514968714189847 
9674137095837778645652621150351 
9969632214348349234653730196586 
1397846105816635294077965449171 
3911263633583030536971422042360 
9864578596169364050929858013943 

Wykorzystanie gdzie zasięg jest mniejszy niż liczba wymaganych elementów: wynik

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

Próbka:

2, 0, 1 

Działa również z negatywnymi zakresów i etapów:

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

Sample wyniki:

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

Można użyć Numpy bibliotekę za szybką odpowiedź, jak pokazano poniżej -

Podane listy fragment kodu dół 6 unikalne cyfry w przedziale od 0 do 5. Można ustawić parametry dla Twojej wygody.

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

Wyjście

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

To nie stawia żadnych ograniczeń co widzimy w random.sample, o których mowa here.

Mam nadzieję, że to trochę pomaga.