如何从python中的一个文件中读取随机行?

问题描述:

有没有内置的方法来做到这一点?如果没有,我怎么能不花费太多的开销呢?如何从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

没有内置,但算法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

寻找一个随机的位置,读一行并丢弃它,然后读取另一行。线路的分布不正常,但这并不总是重要。

+3

尤其是,这使得不可能选择第一行(以及以与每个先前行的长度成比例的概率选取其他行)。我的A也不会产生正态分布(这会很奇怪 - 什么意思,什么变化?!),而是一个统一的分布,这似乎更有可能满足OP对“随机”的含义。 – 2010-08-22 05:38:38

+0

要解决@AlexMartelli指出的问题,请选择第一行,以防随机查找引导您到达最后一行。但是,另一个问题是,一条线与其他线相比具有相对更多的话语将有更高的选择可能性。 – 2016-06-11 20:36:42

这取决于“太多”的开销是什么意思。如果在内存中存储整个文件是可能的,那么像

import random 

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

会做的伎俩。

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

虽然我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

如果您不想翻阅整个文件,您可以搜索到文件的中间,然后向后寻找换行符,并致电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() 

您可以将行添加到随机更改顺序的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) 

这可能体积庞大,但它的工作我猜? (至少对于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) 

希望这可以帮助,但至少没有额外的模块和进口(除了随机)和相对轻巧。