我想在python中的一个非常大的文件中读取两个非连续的行,也就是说,预期结果如下(数字是行号):
1 6(第一次读取第1行和第6行)
2 7(第二次读第2行和第7行)
3 8(第三次读第3和第8行)
4 9
5 10
6 11
7 12
8 13
9 14
10 15
...
...
...
...
..(最后一次读取最后一行和最后一行的第6行)
可以使用枚举方法(文件对象)获取行号。我是python的初学者,只知道如何连续读取两行。您能否与我分享如何获得上述预期结果?谢谢你的时间!
答案 0 :(得分:3)
您可以多次打开该文件。只需跳过第二个文件句柄中的前几行,并使用zip
同时读取它们:
with open(filename, 'r') as handle1, \
open(filename, 'r') as handle2:
for _ in range(5):
handle2.readline()
for line1, line2 in zip(handle1, handle2):
print(line1, line2)
你必须在Python 2中from itertools import izip as zip
让zip
不要将整个文件两次读入内存。
另一种解决方案是使用双端队列,并在从文件读取时在内存中保留5 + 1行:
from collections import deque
lines = deque([], maxlen=6)
with open(filename, 'r') as handle:
for line in handle:
lines.append(line)
if len(lines) == lines.maxlen:
print(lines[0], lines[-1])
这只会读取一次文件,但是如果你的文件很长而且你的两行间隔超过5,你就必须在内存中保留那么多字符串。
答案 1 :(得分:1)
如果您希望对文件进行单次迭代(读取文件一次),那么您可以在itertools
pairwise
配方上编写变体,将第二个迭代器推进5而不是1(使用{ {1}})。这与使用双端队列的@ Blender的答案基本相同,但是解决可能更容易推理的问题的功能性方法(并且证明在没有边缘情况下实现是正确的)。
来自python3 itertools recipe book:
consume
示例解决方案:
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def consume(iterator, n):
"Advance the iterator n-steps ahead. If n is none, consume entirely."
# Use functions that consume iterators at C speed.
if n is None:
# feed the entire iterator into a zero-length deque
collections.deque(iterator, maxlen=0)
else:
# advance to the empty slice starting at position n
next(islice(iterator, n, n), None)
def pairwise(iterable, n=1):
"""Return every pair of items, separated by n items, from iterable
s -> (s[0], s[n]), (s[1], s[n+1]), (s[2], s[2+n]), ..."""
assert n >= 1
a, b = tee(iterable)
# advance leading iterator (b) by n elements
consume(b, n)
return zip(a, b)
with open(filename, 'r') as f:
for a, b in pairwise(f, 5):
print('{}: {}'.format(a, b))
解决方案和此collections.deque
解决方案都需要一次在内存中存储n + 1个项目,以及容器的开销。使用两个文件指针打开文件两次会将内存减少到只有2个项目,但由于磁盘I / O访问次数的两倍(假设操作系统没有从文件中缓存读取),可能会显着减慢。从文件中读取两次风险稍大,因为文件可能在读取时被修改,从而产生不一致的数据。公平地说,修改文件一次或两次迭代会产生可疑的结果。
不言而喻,如果您(仍然)使用Python 2.7,请将pairwise
替换为zip
,除非您想将整个文件内容存储在RAM中并可能导致程序崩溃或系统用于大输入文件。