Próbowałem użyć random.randint(0, 100)
, ale niektóre liczby były takie same. Czy istnieje metoda / moduł tworzenia listy unikalnych liczb losowych?
Uwaga: Poniższy kod jest oparty na odpowiedzi i został dodany po opublikowaniu odpowiedzi. To nie jest część pytania; to jest rozwiązanie.
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);
Odpowiedzi:
Spowoduje to wyświetlenie listy 10 liczb wybranych z zakresu od 0 do 99 bez duplikatów.
Nawiązując do swojej przykład kodu specyficzne, prawdopodobnie chcesz, aby przeczytać wszystkie wiersze z pliku raz , a następnie wybrać losowo wiersze z listy zapisanej w pamięci. Na przykład:
W ten sposób wystarczy, że faktycznie przeczytasz z pliku tylko raz, przed wykonaniem pętli. Jest to o wiele bardziej wydajne niż szukanie z powrotem na początek pliku i
f1.readlines()
ponowne wywoływanie dla każdej iteracji pętli.źródło
Możesz użyć funkcji shuffle z modułu losowego w następujący sposób:
Zauważ, że metoda shuffle nie zwraca żadnej listy, jak można by się spodziewać, a jedynie tasuje listę przekazaną przez referencję.
źródło
Możesz najpierw utworzyć listę liczb od
a
dob
, gdziea
ib
są odpowiednio najmniejszymi i największymi liczbami na liście, a następnie przetasować ją algorytmem Fishera-Yatesa lub metodą Pythonarandom.shuffle
.źródło
Rozwiązanie przedstawione w tej odpowiedzi działa, ale może stać się problematyczne z pamięcią, jeśli wielkość próby jest mała, ale populacja jest ogromna (np.
random.sample(insanelyLargeNumber, 10)
.).Aby to naprawić, poszedłbym z tym:
źródło
random.sample
stosuje to podejście do małej liczby próbek z dużej populacji, więc ten problem z pamięcią tak naprawdę już nie istnieje. Chociaż w momencie pisania tej odpowiedzi realizacjarandom.shuffle
mogła wyglądać inaczej.Liniowy kongruencjalny generator liczb pseudolosowych
Ten problem można rozwiązać za pomocą prostego liniowego generatora kongruencji . Wymaga to stałego narzutu pamięci (8 liczb całkowitych) i maksymalnie 2 * (długość sekwencji) obliczeń.
Wszystkie inne rozwiązania zużywają więcej pamięci i więcej mocy obliczeniowej! Jeśli potrzebujesz tylko kilku losowych sekwencji, ta metoda będzie znacznie tańsza. W przypadku zakresów rozmiarów
N
, jeśli chcesz generować w kolejnościN
unikalnychk
sekwencji lub więcej, polecam zaakceptowane rozwiązanie przy użyciu wbudowanych metod,random.sample(range(N),k)
ponieważ zostało to zoptymalizowane w Pythonie pod kątem szybkości.Kod
Stosowanie
Użycie tej funkcji „random_range” jest takie samo jak w przypadku każdego generatora (np. „Range”). Przykład:
Przykładowe wyniki
źródło
prime
, funkcja zwróci mi tylko 4 możliwe odpowiedzi, ponieważvalue
jest to jedyna losowo wybrana rzecz z 4 możliwymi wartościami, kiedy potrzebujemy co najmniej (4 wybierz 2) = 6, (pozwalając na nielosowe porządkowanie).random_range(2,4)
zwróci wartości {(1, 0), (3, 2), (2, 1), (0, 3)}, ale nigdy pary (3,1) (lub (1,3)). Czy spodziewasz się nowych, losowo generowanych dużych liczb pierwszych dla każdego wywołania funkcji?random_range(v)
powraca dov
unikalnych sekwencjiv!
)Jeśli lista N liczb od 1 do N jest generowana losowo, to tak, istnieje możliwość, że niektóre liczby mogą się powtórzyć.
Jeśli chcesz otrzymać listę liczb od 1 do N w kolejności losowej, wypełnij tablicę liczbami całkowitymi od 1 do N, a następnie użyj tasowania Fishera-Yatesa lub Pythona
random.shuffle()
.źródło
Jeśli potrzebujesz próbkować bardzo duże liczby, nie możesz użyć
range
bo rzuca:
Ponadto, jeśli
random.sample
nie można wyprodukować żądanej liczby przedmiotów ze względu na zbyt mały zakresrzuca:
Ta funkcja rozwiązuje oba problemy:
Użycie z bardzo dużymi liczbami:
Przykładowy wynik:
Zastosowanie, w którym zakres jest mniejszy niż liczba żądanych pozycji:
Przykładowy wynik:
Działa również z ujemnymi zakresami i krokami:
Przykładowe wyniki:
źródło
Możesz użyć Numpy biblioteki aby uzyskać szybką odpowiedź, jak pokazano poniżej -
Podany fragment kodu zawiera 6 unikalnych liczb z zakresu od 0 do 5. Możesz dostosować parametry dla swojej wygody.
Wynik
Nie nakłada żadnych ograniczeń, jak widzimy w przykładzie losowym, o którym mowa tutaj .
Mam nadzieję, że to trochę pomoże.
źródło
Podana tutaj odpowiedź działa bardzo dobrze w odniesieniu do czasu, a także pamięci, ale jest nieco bardziej skomplikowana, ponieważ wykorzystuje zaawansowane konstrukcje Pythona, takie jak yield. Prostsza odpowiedź sprawdza się w praktyce, ale problem z tą odpowiedzią jest to, że może generować wiele fałszywych całkowite zanim faktycznie konstruowania wymaganego zestawu. Wypróbuj z populacjąSize = 1000, sampleSize = 999. Teoretycznie istnieje szansa, że to się nie zakończy.
Poniższa odpowiedź dotyczy obu kwestii, ponieważ jest deterministyczna i nieco wydajna, choć obecnie nie jest tak wydajna jak pozostałe dwie.
gdzie funkcje getElem, percolateUp są zdefiniowane poniżej
Wreszcie średni czas wynosił około 15 ms dla dużej wartości n, jak pokazano poniżej,
źródło
random.randint
funkcję 3996 razy, podczas gdy druga - cca. 6000 razy. Niezbyt duża poprawa, co?Aby otrzymać program, który generuje listę wartości losowych bez duplikatów, który jest deterministyczny, wydajny i zbudowany z podstawowych konstrukcji programistycznych, rozważ funkcję
extractSamples
zdefiniowaną poniżej:Podstawową ideą jest śledzenie odstępów czasu
intervalLst
dla możliwych wartości, z których należy wybrać nasze wymagane elementy. Jest to deterministyczne w tym sensie, że gwarantujemy wygenerowanie próbki w ramach ustalonej liczby kroków (wyłącznie w zależności odpopulationSize
isampleSize
).Aby skorzystać z powyższej funkcji w celu wygenerowania naszej wymaganej listy,
Możemy również porównać z wcześniejszym rozwiązaniem (dla niższej wartości populacjiSize)
Zwróć uwagę, że zmniejszyłem
populationSize
wartość, ponieważ powoduje to błąd pamięci dla wyższych wartości podczas korzystania zrandom.sample
rozwiązania (również wspomnianego w poprzednich odpowiedziach tutaj i tutaj ). W przypadku powyższych wartości możemy również zauważyć, żeextractSamples
przewyższa torandom.sample
podejście.PS: Chociaż podstawowe podejście jest podobne do mojej wcześniejszej odpowiedzi , istnieją istotne modyfikacje we wdrażaniu, a także w podejściu, wraz z poprawą przejrzystości.
źródło
Bardzo prosta funkcja, która również rozwiązuje Twój problem
źródło
Problem z podejściami opartymi na zestawach („jeśli wartość losowa w zwracanych wartościach, spróbuj ponownie”) polega na tym, że ich czas działania jest nieokreślony z powodu kolizji (które wymagają kolejnej iteracji „spróbuj ponownie”), zwłaszcza gdy zwracana jest duża liczba losowych wartości z zakresu.
Alternatywą, która nie jest podatna na to niedeterministyczne środowisko wykonawcze, jest:
źródło
źródło
Jeśli chcesz mieć pewność, że dodawane liczby są unikalne, możesz użyć obiektu Set
jeśli używasz wersji 2.7 lub nowszej, lub zaimportuj moduł sets, jeśli nie.
Jak wspominali inni, oznacza to, że liczby nie są naprawdę losowe.
źródło
do próbkowania liczb całkowitych bez zamiany między
minval
amaxval
:z jax:
źródło
n_samples
z nich? Jakie jest Twoje uzasadnienie tego podejścia? Czy możesz wyjaśnić, jakie są zalety twojego podejścia w porównaniu z dowolną z dużej liczby istniejących odpowiedzi (większość z nich sprzed 8 lat)?random.shuffle
, które wykorzystują Mersenne Twister, który jest znacznie wolniejszy niż algorytmy oferowane przez numpy (i prawdopodobnie jax). numpy i jax pozwalają na inne algorytmy generowania liczb losowych. jax umożliwia także kompilację i różnicowanie w jit, co może być przydatne w przypadku różnicowania stochastycznego. również, jeśli chodzi o „prawdopodobnie dużą” tablicę, niektóre odpowiedzirandom.shuffle
, którerandom.shuffle
mówiąc „ używa Mersenne Twister” - jest to tasowanie Fisher-Yates, jak wspomniano w kilku odpowiedziach. Ma liniową złożoność czasową, więc nie może być asymptotycznie wolniejszy niż algorytmy oferowane przez jakąkolwiek inną bibliotekę, numpy lub w inny sposób. Jeśli numpy jest szybszy, to tylko dlatego, że jest zaimplementowany w C, ale to nie gwarantuje wygenerowania ogromnej permutacji (takiej, która może nawet nie pasować do pamięci), tylko po to, aby wybrać z niej kilka elementów. Nie ma jednej odpowiedzi poza twoją, która to robi.random
moduł jest napisany w Pythonie, więc możesz łatwo wyświetlić jego źródło (spróbujrandom.__file__
).Z CLI w Win XP:
W Kanadzie mamy Lotto 6/49. Po prostu zawijam powyższy kod w lotto.bat i uruchamiam
C:\home\lotto.bat
lub po prostuC:\home\lotto
.Ponieważ
random.randint
często powtarza liczbę, używamset
z,range(7)
a następnie skracam ją do długości 6.Czasami, jeśli liczba powtarza się więcej niż 2 razy, wynikowa długość listy będzie mniejsza niż 6.
EDYCJA: Jednak
random.sample(range(6,49),6)
jest to właściwy sposób.źródło
źródło
print len(result), len(set(result))
. Można by się spodziewać, żeresult
będzie miał unikalne elementy tylko przy każdej1.0851831788708547256608362340568947172111832359638926... × 10^20
próbie.