如何从python中的一个文件中读取随机行?
没有内置,但算法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从MIX翻译为python – aaronasterling 2010-08-22 05:45:12
这是油藏采样,对不对? – HenryR 2010-08-22 05:50:20
我一直认为'random.choice()'函数应该可以在任意迭代器以及序列上工作,完全实现上述算法。 – 2010-08-22 05:54:39
寻找一个随机的位置,读一行并丢弃它,然后读取另一行。线路的分布不正常,但这并不总是重要。
尤其是,这使得不可能选择第一行(以及以与每个先前行的长度成比例的概率选取其他行)。我的A也不会产生正态分布(这会很奇怪 - 什么意思,什么变化?!),而是一个统一的分布,这似乎更有可能满足OP对“随机”的含义。 – 2010-08-22 05:38:38
要解决@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'))))
如果任务只是读取一行,那么将完整文件加载到内存中是没有意义的。 – 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))
我刚刚真的很高兴,因为我看到有人谁可以从我的包中受益!对不起,没有答案,但该软件包肯定可以应用于其他许多问题。
我有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)
希望这可以帮助,但至少没有额外的模块和进口(除了随机)和相对轻巧。
@Greg这是Perl,而不是Python – quantumSoup 2010-08-22 05:29:29
@quantumSoup:这个问题在其示例中使用Perl,但问题是语言不可知。最有用的答案使用伪代码,很容易翻译成您选择的语言。 – 2010-08-22 05:32:04
谢谢,我也发现这个帮助很多:http://mail.python.org/pipermail/tutor/2007-July/055635.html 你必须把它们读入内存。 – Shane 2010-08-22 05:35:51