2010-08-22 222 views
26

有沒有內置的方法來做到這一點?如果沒有,我怎麼能不花費太多的開銷呢?如何從python中的一個文件中讀取隨機行?

+0

@Greg這是Perl,而不是Python – quantumSoup 2010-08-22 05:29:29

+2

@quantumSoup:這個問題在其示例中使用Perl,但問題是語言不可知。最有用的答案使用僞代碼,很容易翻譯成您選擇的語言。 – 2010-08-22 05:32:04

+0

謝謝,我也發現這個幫助很多:http://mail.python.org/pipermail/tutor/2007-July/055635.html 你必須把它們讀入內存。 – Shane 2010-08-22 05:35:51

回答

51

沒有內置,但算法R(3.4.2)從Knuth的(沃特曼的「水庫算法」),「計算機程序設計藝術」是很好的(在一個非常簡化的版本):

import random 

def random_line(afile): 
    line = next(afile) 
    for num, aline in enumerate(afile): 
     if random.randrange(num + 2): continue 
     line = aline 
    return line 

num + 2產生序列2,3,4 ... randrange因此將爲0,其可能性爲1.0/(num + 2) - 這就是我們必須替換當前選定行的概率(參考算法的樣本大小1的特例 - 請參閱克努特的書證明了正確性==當然,我們也是在一個足夠小的「水庫」的情況下適合記憶; - )...和確切的概率我們等等。

+1

+1從MIX翻譯爲python – aaronasterling 2010-08-22 05:45:12

+2

這是油藏採樣,對不對? – HenryR 2010-08-22 05:50:20

+6

我一直認爲'random.choice()'函數應該可以在任意迭代器以及序列上工作,完全實現上述算法。 – 2010-08-22 05:54:39

1

尋找一個隨機的位置,讀一行並丟棄它,然後讀取另一行。線路的分佈不正常,但這並不總是重要。

+3

尤其是,這使得不可能選擇第一行(以及以與每個先前行的長度成比例的概率選取其他行)。我的A也不會產生正態分佈(這會很奇怪 - 什麼意思,什麼變化?!),而是一個統一的分佈,這似乎更有可能滿足OP對「隨機」的含義。 – 2010-08-22 05:38:38

+0

要解決@AlexMartelli指出的問題,請選擇第一行,以防隨機查找引導您到達最後一行。但是,另一個問題是,一條線與其他線相比具有相對更多的話語將有更高的選擇可能性。 – 2016-06-11 20:36:42

9

這取決於「太多」的開銷是什麼意思。如果在內存中存儲整個文件是可能的,那麼像

import random 

random_lines = random.choice(open("file").readlines()) 

會做的伎倆。

23
import random 
lines = open('file.txt').read().splitlines() 
myline =random.choice(lines) 
print(myline) 

對於很長的文件: 尋求隨機發生在文件基礎上它的長度和位置(或換行和文件結束)後發現兩個換行符。如果原始查找位置是<,如果我們結束了最後一行,則在文件開始前或開始後再執行100個字符。

然而,這是過於複雜,因爲文件是iterator.So使它名單,並採取random.choice(如果你需要很多,使用random.sample):

import random 
print(random.choice(list(open('file.txt')))) 
+9

如果任務只是讀取一行,那麼將完整文件加載到內存中是沒有意義的。 – iankit 2016-02-23 11:08:54

6

雖然我4年晚,我認爲我有最快的解決方案。最近我寫了一個叫做linereader的Python包,它允許你操作文件句柄的指針。

下面是簡單的解決方案,以得到一個隨機符合這個包:

from random import randint 
from linereader import dopen 

length = #lines in file 
filename = #directory of file 

file = dopen(filename) 
random_line = file.getline(randint(1, length)) 

第一次這樣做是最糟糕的,因爲linereader具有編譯輸出文件中的一個特殊格式。完成後,無論文件大小如何,linereader都可以快速訪問文件中的任何行。

如果您的文件非常小(足夠小以適合MB),那麼您可以用copen替換dopen,並且它會在內存中創建一個緩存的文件條目。這不僅速度更快,而且可以在文件加載到內存中時獲取文件中的行數;它是爲你完成的。你所需要做的就是生成隨機行號。這裏是一些示例代碼。

from random import randint 
from linereader import copen 

file = copen(filename) 
lines = file.count('\n') 
random_line = file.getline(randint(1, lines)) 

我剛剛真的很高興,因爲我看到有人誰可以從我的包中受益!對不起,沒有答案,但該軟件包肯定可以應用於其他許多問題。

+0

我有ValueError行號。沒有找到,但行號。小於文件的大小。 – kakarukeys 2017-06-30 07:46:11

2

如果您不想翻閱整個文件,您可以搜索到文件的中間,然後向後尋找換行符,並致電readline

這裏是一個Python3腳本不只是此,用這種方法

一個缺點是短線具有顯示出來的較低的情形產生。

def read_random_line(f, chunk_size=16): 
    import os 
    import random 
    with open(f, 'rb') as f_handle: 
     f_handle.seek(0, os.SEEK_END) 
     size = f_handle.tell() 
     i = random.randint(0, size) 
     while True: 
      i -= chunk_size 
      if i < 0: 
       chunk_size += i 
       i = 0 
      f_handle.seek(i, os.SEEK_SET) 
      chunk = f_handle.read(chunk_size) 
      i_newline = chunk.rfind(b'\n') 
      if i_newline != -1: 
       i += i_newline + 1 
       break 
      if i == 0: 
       break 
     f_handle.seek(i, os.SEEK_SET) 
     return f_handle.readline() 
0

您可以將行添加到隨機更改順序的set()中。

filename=open("lines.txt",'r') 
f=set(filename.readlines()) 
filename.close() 

要找到第1行:

print(next(iter(f))) 

要找到第三行:

print(list(f)[2]) 

要列出集合中的所有行:

for line in f: 
    print(line) 
0

這可能體積龐大,但它的工作我猜? (至少對於TXT文件)

import random 
choicefile=open("yourfile.txt","r") 
linelist=[] 
for line in choicefile: 
    linelist.append(line) 
choice=random.choice(linelist) 
print(choice) 

它讀取文件中的每一行,並將其添加到列表中。然後它從列表中選擇一個隨機行。 如果你想一次它選擇了刪除行,只是做

linelist.remove(choice) 

希望這可以幫助,但至少沒有額外的模塊和進口(除了隨機)和相對輕巧。

相關問題