如何仅在满足条件时读取python中的行块?

如何仅在满足条件时读取python中的行块?,python,Python,我需要创建一个脚本,读取四行,如果满足条件,则读取文件中的下四行,依此类推。如果不满足条件,脚本必须从先前读取块的第二行重新启动测试。因此,下一个块的第一行变成了新的第四行。例如,我想从下面的文件中检索求和4的所有块 printf "1\n1\n1\n1\n2\n1\n1\n1\n1" > file1.txt #In BASH 从1到4的行和4相加,因此它们产生一个正结果。从5到8的行和5相加,因此它们会产生一个负结果,必须从第6行开始,到第9行结束,再加上4,从而产生一个正结果。我知道

我需要创建一个脚本,读取四行,如果满足条件,则读取文件中的下四行,依此类推。如果不满足条件,脚本必须从先前读取块的第二行重新启动测试。因此,下一个块的第一行变成了新的第四行。例如,我想从下面的文件中检索求和4的所有块

printf "1\n1\n1\n1\n2\n1\n1\n1\n1" > file1.txt #In BASH
从1到4的行和4相加,因此它们产生一个正结果。从5到8的行和5相加,因此它们会产生一个负结果,必须从第6行开始,到第9行结束,再加上4,从而产生一个正结果。我知道我可以这样做

with open("file1.txt") as infile:
  while not EOF:
    lines = []
    for i in range(next N lines):
        lines.append(infile.readline())
    make_the_sum(lines)

但这将使读者移动四行,如果总和大于4,则不可能向后移动。我怎样才能达到这个效果?考虑到我的文件很大,我不能把它们装入内存中。

我通过忽略文件的结尾来简化。您可以使用tell和seek来处理恢复早期职位的操作(您可以根据需要在列表中保存任意多个职位,例如:

>>> with open('testmedium.txt') as infile:
...     times = 0
...     EOF = 0
...     while not EOF:
...         pos = infile.tell()
...         print(f"\nPosition is {pos}")
...         lines = []
...         for i in range(4):
...             lines.append(infile.readline())
...         [print(l[:20]) for l in lines]
...         if times==0 and '902' in lines[0]:
...             times = 1
...             infile.seek(pos)
...         elif '902' in lines[0]:
...             break

Position is 0
271,848,690,44,511,5
132,427,793,452,85,6
62,617,183,843,456,3
668,694,659,691,242,

Position is 125
902,550,177,290,828,
326,603,623,79,803,5
803,949,551,947,71,8
661,881,124,382,126,

Position is 125
902,550,177,290,828,
326,603,623,79,803,5
803,949,551,947,71,8
661,881,124,382,126,

>>>

以下代码将把行读入“缓存”(只是一个列表),并在缓存有四行时对缓存行执行一些操作。如果测试通过,缓存将被清除。如果测试失败,缓存将更新为仅包含缓存的最后三行。您可以根据需要在If-else块中执行其他操作

def passes_test(lines, target_value=4):
    return sum([int(line) for line in lines]) == target_value

with open('file1.txt') as f:
    cached = []
    for line in f:
        cached.append(line)
        if len(cached) == 4:
            if passes_test(cached):
                cached = []
            else:
                cached = cached[1:]

正如Martijn所说

with open("file1.txt") as f:
    rd = lambda: int(next(f))
    try:
        a, b, c, d = rd(), rd(), rd(), rd()
        if a + b + c + d == 4:
            # found a block
            a, b, c, d = rd(), rd(), rd(), rd()
        else:
            # nope
            a, b, c, d = b, c, d, rd()
    except StopIteration:
        # found end of file

但您可以加载已读的4行,并根据需要重新使用,对吗?只需存储最新的4行即可。当剩下的4行不到时会发生什么情况?我尝试了您的解决方案,但它肯定有错误。它只验证了4个数字中的第一个块,然后停止。