2013-08-27 34 views
3

我有一個文本文件,它的長度爲10k行,我需要構建一個函數,每次從該文件中提取10個隨機行。我已經找到了如何使用numpy在Python中生成隨機數字,以及如何打開文件,但我不知道如何將它們混合在一起。請幫忙。從文件中檢索10個隨機行

+0

你的意思是10000行或10KB大小的文件? – elyase

+0

對不起,我的意思是10000行。 – user2719565

+0

我改變了問題,謝謝。 – user2719565

回答

5

如果你知道你的文件是正是 10K 長,那麼你可以使用linecache

import random 
import linecache 

def random_lines(filename) 
    idxs = random.sample(range(10000), 10) 
    return [linecache.getline(filename, i) for i in idxs] 

此方法返回10個隨機行的列表,您可以用打印:

for line in random_lines('file.txt'): 
    print line 
+0

10K文件不大可能是10000行;這意味着平均行長度爲0.024個字符... – abarnert

+0

@abarnert,我理解10K = 10000行長,但它也可以是10K = 10Kb或10KB,正如您所提到的。 – elyase

0

嘗試linecache:

import linecache 
#put your 3 randoms into an array in whichever way you are doing it 
lines = [3,45,678] #use your existing code here 
for i in lines: 
    linecache.getline('/etc/file', i) 
+0

不知道文件有多長時間,他怎麼知道範圍來生成隨機數? – abarnert

2

你可以使用這個代碼不關心文件的長度,但在極少數情況下你可能會得到重複:

from random import choice 
lines = [a.strip() for a in open("yourfile").readlines()] 
result = [choice(lines) for a in range(10)] 

result是含有名爲yourfile文件隨機選擇10行的列表。

+0

對於小至10的範圍,'xrange(10)'可能會是_lowlow_,而不是更快......並且很難相信這種差異會以任何方式出現。 – abarnert

+0

從Apple 64位CPython 2.7.2的快速測試中,我得到了範圍(10)中的'%timeit':pass''需要17.1ns,我在xrange(10)中使用'%timeit':pass''需要18.1ns。當然你通過創建列表浪費了整個92字節,但是很難想象它會在哪裏重要...... – abarnert

+0

@abarnert感謝您告訴我,我實際上並不知道xrange()在某些情況下可能會變慢;我更新了我的答案。 – 2013-08-27 02:10:35

5

如果您知道該文件有多長行,可以使用linecache,如其他答案所示。但只知道它的大小是10K就不會告訴你它有多長的行數。

如果知道該文件是小到足以放入內存和一個10K的文件很容易足夠小,只是將它讀入內存:

import random 

with open('file.txt') as f: 
    lines = list(f) 
for i in range(10): 
    print(random.choice(lines)) 

但是,如果你不知道多久文件是,並且不能將它全部讀入內存?然後,你需要做兩關:

import linecache 
import random 

with open('file.txt') as f: 
    linecount = sum(1 for line in f) 
for i in range(10): 
    print(linecache.getline('file.txt', random.range(linecount))) 

注意,這兩個會在每行結束離開換行。如果你想擺脫這些,你可以將第一個例子從list(f)更改爲[line.rstrip() for line in f],或者在print中調用rstrip(),或在print中使用end=''(Python 3.x)或尾隨逗號(Python 2.x) 。對於linecache示例,第一個顯然不起作用,但您仍然可以執行其他任何一個。


另外請注意,我用的,而不是在這裏使用numpy的STDLIB random庫。如果您只是生成10個隨機數字以用於普通Python代碼,則沒有理由使用numpy。 (另一方面,如果您在此處有一個很好的理由使用numpy,您可能需要將行讀入pandas表中,並將隨機索引應用於該表。)

+0

感謝和抱歉的困惑,我的意思是10000lines,如果我被允許,我會upvote。 – user2719565

0

如果你不知道你的文件的行數,你可以數得過來,例如,此代碼:

line_count = 0 
with open(filename) as file: 
    for line in file: 
     line_count += 1 

然後,您將能夠產生內的隨機數範圍[0, line_count)

import random 
lines_to_read = [] 
for i in range(10): 
    line = random.randint(0, line_count - 1) 
    lines_to_read.append(line) 

最後,再次讀取該文件,選擇隨機選擇這些線路,做任何你想要它們,例如,打印出來:

with open(filename) as file: 
    for index, line in enumerate(file): 
     if index in lines_to_read: 
      print line 

我希望它能幫助你!乾杯!

+0

這會迫使他們按照排序順序打印出來(例如,如果您隨機選擇了「[44,66,41,85,5,94,95,90,67,58]」,則實際上會打印出5,41行,44,58,66,67,85,90,94,95。所以它大大減少了可能的輸出範圍 – abarnert

+0

此外,爲什麼使用'randint(0,b-1)'而不是'randrange(0, b)''''''或'randrange(b)'?你只是要求自己的錯誤。 – abarnert

+0

你可能是對的,但是這個問題並不需要特殊的輸出命令。 – marcelrf

1

可以用一遍完成這項工作,也不需要將整個文件加載到內存中。儘管代碼本身將變得更加複雜並且大部分都是不需要的,除非該文件是巨大的。

訣竅如下:

假設我們只需要一個隨機線,那麼首先救人第一線到一個變量,那麼對於第i行,以概率1替換當前/我。到達文件結尾時返回保存的行。 對於10個隨機行,然後有10個元素的列表,併爲該文件中的每一行執行10次處理。