如何在python

时间:2018-03-13 01:16:20

标签: python

我想在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的初学者,只知道如何连续读取两行。您能否与我分享如何获得上述预期结果?谢谢你的时间!

2 个答案:

答案 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 zipzip不要将整个文件两次读入内存。

另一种解决方案是使用双端队列,并在从文件读取时在内存中保留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中并可能导致程序崩溃或系统用于大输入文件。