2013-02-17 89 views
8

我想爲我的學校(我們有一個經濟體系)製作一個彩票計劃。如何從文本文件中選擇一條隨機線

我的程序生成數字並將其保存到文本文件中。當我想從生成器中「拉出」數字時,我希望它確保有一個贏家。

問:我如何讓Python從我的文本文件中選擇一個隨機線並將該輸出作爲該數字輸出?

回答

15

How do I have python select a random line out of my text file and give my output as that number?

假設該文件是比較小的,以下是可能做到這一點最簡單的方法:

import random 
line = random.choice(open('data.txt').readlines()) 
+0

出於某種原因,當我嘗試你的方法我收到以下消息 _italic_ ** **大膽'回溯(最近通話最後一個): 文件「/用戶/ pilotkid /文檔/彩票。 py「,第338行,在 line = random.choice(open('KEEP-IMPORANT.txt')。readlines()) 文件」/System/Library/Frameworks/Python.framework/Versions/2.7/lib/ python2.7/random.py「,第274行,選擇 return seq [int(self.random()* len(seq))]#如果seq爲空,則引發IndexError IndexError:列表索引超出範圍 註銷 [處理完成] ' – 2013-02-18 22:07:03

+0

文件是否爲空? – NPE 2013-02-19 06:26:49

+0

事實證明它不是在製作文件。奇怪的感謝你所有的時間 – 2013-02-20 03:59:40

2

關閉我的頭頂:

import random 
def pick_winner(self): 
    lines = [] 
    with open("file.txt", "r") as f: 
     lines = f.readlines(); 
    random_line_num = random.randrange(0, len(lines)) 
    return lines[random_lines_num] 
1

另一種方法:

import random, fileinput 

text = None 
for line in fileinput.input('data.txt'): 
    if random.randrange(fileinput.lineno()) == 0: 
     text = line 
print text 

分佈:

$ seq 1 10 > data.txt 

# run for 100000 times 
$ ./select.py > out.txt 

$ wc -l out.txt 
100000 out.txt 

$ sort out.txt | uniq -c 
    10066 1 
    10004 10 
    10023 2 
    9979 3 
    9926 4 
    9936 5 
    9878 6 
    10023 7 
    10154 8 
    10011 9 

我沒有看到skewnes但也許數據集太小......

+0

這扭曲了對文件中早先出現的數字的選擇。 – chepner 2013-02-17 19:00:46

+0

@chepner - 查看更新。沒有看到歪斜... – 2013-02-17 19:38:10

+0

它的傾斜有點不同於我的預期(我沒有仔細看過你的代碼)。你基本上是從1到10中選擇一組數字,然後輸出最大的數字。所以,儘管選擇1作爲集合的一部分的可能性更大(事實上,它總是*是集合的一部分,因爲'randrange(0,1)'將總是返回0),它將永遠不會被返回除非*不選*其他號碼。注意你的分佈看起來像一個倒轉的鐘形曲線,極端數字顯着地選擇了中間數字。 – chepner 2013-02-17 20:12:50

2

有輕微的修改輸入文件(存儲在第一線的項目數),則可以無需首先將整個文件讀入內存,統一選擇一個數字。

import random 
def choose_number(frame): 
    with open(fname, "r") as f: 
     count = int(f.readline().strip()) 
     for line in f: 
      if not random.randrange(0, count): 
       return int(line.strip()) 
      count-=1 

假設你有100個號碼。選擇第一個數字的概率是1/100。選擇第二個數字的概率是(99/100)(1/99)= 1/100。選擇第三個數字的概率是(99/100)(98/99)(1/98)= 1/100。我將跳過正式的證明,但選擇100個數字中任何一個的可能性是1/100。

將計數存儲在第一行並不是必須的,但它可以節省讀取整個文件以計算行數的麻煩。無論哪種方式,您都不需要將整個文件存儲在內存中,以相同的概率選擇任何一行。

+1

,無需爲每行調用「random.randrange」。只需隨機選擇行號並前進到該行。 – mata 2013-09-09 00:02:53

9

如果該文件是非常大的 - 你可以尋求到指定的文件大小的文件在隨機位置,然後得到下一個完整行:

import os, random 
def get_random_line(file_name): 
    total_bytes = os.stat(file_name).st_size 
    random_point = random.randint(0, total_bytes) 
    file = open(file_name) 
    file.seek(random_point) 
    file.readline() # skip this line to clear the partial line 
    return file.readline() 
+3

該方法會縮短選擇的機率,因此如果您真的想讓您的隨機生成器以相同的概率選擇每一行,這不是一個好的選擇。 – mata 2013-09-08 23:57:04

+0

它也不會返回第一行,並且在random_point位於最後一行時不會返回任何行。 – 2017-06-13 12:53:38

-1

我看到一個Python的教程,發現這個片斷:

def randomLine(filename): 
#Retrieve a random line from a file, reading through the file once 
     fh = open("KEEP-IMPORANT.txt", "r") 
     lineNum = 0 
     it = '' 

     while 1: 
       aLine = fh.readline() 
       lineNum = lineNum + 1 
       if aLine != "": 
         # 
         # How likely is it that this is the last line of the file ? 
         if random.uniform(0,lineNum)<1: 
           it = aLine 
       else: 
         break 
     nmsg=it 
     return nmsg 
     #this is suposed to be a var pull = randomLine(filename) 
4
def random_line(): 
    line_num = 0 
    selected_line = '' 
    with open(filename) as f: 
     while 1: 
      line = f.readline() 
      if not line: break 
      line_num += 1 
      if random.uniform(0, line_num) < 1: 
       selected_line = line 
    return selected_line.strip() 

雖然大部分這裏給出的方法會工作,但他們往往加載內存中的整個文件一次。但不是這種方法。所以即使文件很大,這也是可行的。

該方法乍一看並不是非常直觀。這背後的定理表明,當我們看到N行時,有一個恰好爲1/N的概率,他們每個都被選中。

From Page no 123 of 'Python Cookbook

相關問題