2012-03-18 47 views
42

我嘗試使用random.randint(0, 100),但有些數字是相同的。有沒有一種方法/模塊來創建一個列表唯一的隨機數字?如何創建獨特的隨機數列表?

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

如果他們是獨特的,那麼他們並不是真正的隨機。 – 2012-03-18 02:38:06

+1

@ IgnacioVazquez-Abrams im試圖實施一種方法我的教授稱爲「bootstrapping」,我們正在搜索引擎上做一些「研究」。 – iCodeLikeImDrunk 2012-03-18 02:47:32

+0

@ IgnacioVazquez-Abrams他們是如果他們代表隨機選擇而不替換。這是一個關於一般使用的編程語言的問題......我們使用*它的東西 – 2016-02-04 21:34:38

回答

78

這將返回一個從0到99範圍內選擇的10個數字的列表,沒有重複。

random.sample(range(100), 10) 

參照特定的代碼示例,你可能想從文件一次讀取所有的行,然後選擇在內存中保存的列表隨機線。例如:

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

這樣,您只需要在循環之前從文件中實際讀取一次。這樣做要比找回文件的開始更有效率,並且每次循環迭代都要再次調用f1.readlines()

+0

我也試過這個,lines = random.sample(f1.readlines(),40);它不斷給我「樣本大於人口」,當我試圖通過一個for循環運行..任何建議? – iCodeLikeImDrunk 2012-03-18 02:38:51

+1

你的源代碼包含少於40行,所以'random.sample()'不能給你一個沒有重複的40行的列表。 – 2012-03-18 02:39:49

+0

列表調用是不必要的,我認爲(對於2和3)。 – DSM 2012-03-18 02:39:55

3

如果從1到N的N個數字的列表是隨機生成的,那麼是的,可能會重複某些數字。

如果您需要隨機順序從1到N的數字列表,請使用inegeters 1到N填充數組,然後使用Fisher-Yates shuffle

更新:作爲@格雷格指出:由於這是Python的,使用random.shuffle()

7

爲什麼不創建的1..100列表,並與Fisher-Yates算法洗牌呢?

+15

或者,因爲這是Python,所以'random.shuffle()'... – 2012-03-18 02:40:13

+3

有時只是第一個是不夠的... :) – 2012-03-18 02:44:59

1

如果你希望確保所添加的編號是唯一的,你可以使用,如果使用2.7或更高版本,Set object

,或者如果不導入套模塊。

正如其他人所提到的,這意味着數字並不是真正的隨機數。

6

Greg Hewgill的作品(+1),但如果樣本量很小,但人口數量巨大(例如random.sample(insanelyLargeNumber, 10)),則記憶可能會出現問題。

爲了解決這個問題,我會去這樣的:

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

可以使用洗牌函數從random模塊是這樣的:在這裏

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 

注意洗牌方法沒有按不會像所期望的那樣返回任何列表,它只會拖曳通過引用傳遞的列表。

0

在Win XP的命令行:

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

在加拿大,我們有6/49樂透。我只是將上面的代碼包裝在lotto.bat中,然後運行C:\home\lotto.batC:\home\lotto

由於random.randint經常重複的數,我使用setrange(7),然後將其縮短的6

長度偶爾如果一個重複數目所得到的列表長度的2倍以上將小於6

編輯:但是,random.sample(range(6,49),6)是正確的路要走。

0

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

2

如果您需要的採樣非常大的數字,不能使用range

random.sample(range(10000000000000000000000000000000), 10) 

,因爲它拋出:

OverflowError: Python int too large to convert to C ssize_t 

另外,如果random.sample不能產生想要的項目數由於範圍太小

random.sample(range(2), 1000) 

它拋出:

ValueError: Sample larger than population 

此功能解決兩個問題:

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

中的用法非常大的數字:

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

樣品結果:

7822019936001013053229712669368 
6289033704329783896566642145909 
2473484300603494430244265004275 
5842266362922067540967510912174 
6775107889200427514968714189847 
9674137095837778645652621150351 
9969632214348349234653730196586 
1397846105816635294077965449171 
3911263633583030536971422042360 
9864578596169364050929858013943 

使用其中的範圍比要求的項目數量較小:

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

樣品結果:

2, 0, 1 

它還可以與負範圍和步驟:

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

樣品結果:

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

您可以使用numpy的庫進行快速的答案如下 -

由於代碼片斷清單跌6個獨特數字0到5 之間的範圍內可以調整參數,爲您的舒適。

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

輸出

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

它不把任何約束,因爲我們在random.sample看到稱爲here

希望這會有所幫助。