在Python中,将文件中的行作为带有两个单元格的移位寄存器读取

2024-05-15 21:19:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要读取一个文件的行,以这样的方式,将表现为一个移位寄存器与两个单元。 例如:

with open("filename", 'r') as file:

 --first iteration--
 present = line1
 next  = line2
    do something

 --second iteration--
 present = line2
 next = line3
   do something

 --third iteration--
 present = line3
 next = line 4
    do someting

 and so on....

它可以用open(file, 'r')来完成,但不能保证文件会在脚本停止时关闭 由于在最后一次迭代之前“做点什么”的原因。你知道吗

有什么优雅的方法吗?你知道吗


Tags: 文件with方式opendo寄存器somethingfile
3条回答

Tim's answerBlckknght's answer是好的。要添加到解决方案池,还可以使用deque:

from collections import deque
n = 2
with open('myfile', 'r') as infile:
    window = deque(maxlen=n)
    for line in infile:
        window.append(line)
        do_something(*window)

更一般地,您可以创建一个生成器,从deque生成:

def sliding_window(iterable, n=2, fill_value=None, add_padding=False):
    it = iter(iterable)
    if add_padding:
        window = deque([fill_value for _ in range(n-1)], maxlen=n)
        window.append(next(it))
    else:
        window = deque([next(iterable) for _ in range(n)], maxlen=n)

    yield tuple(window)

    for item in it:
        window.append(it)
        yield tuple(window)

    if add_padding:
        for _ in range(n-1):
            window.append(fill_value)
            yield tuple(window)

请注意,如果iterable中的值少于n,则上述实现将生成一个空生成器。你知道吗

当然可以:

with open("filename", 'r') as file:
    current_line = next(file)  # Get 1st line, advance iterator to 2nd line
    for next_line in file:
        do_something(current_line, next_line)
        current_line = next_line

蒂姆的回答很好。一个“更奇特”的解决方案是使用pairwise配方,使用itertools.tee,如^{} docs所示:

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

tee是一个非常简洁的函数。它可以在任何时候使用,你想迭代同一个iterable多次。如果您或多或少地并行地使用所有迭代器(而不是运行一个迭代以完成下一个迭代等等),那么它比将整个iterable转储到list或其他可以反复迭代的容器中更节省空间。你知道吗

基本上,您向它传递一个iterable对象,它返回许多独立的迭代器(默认情况下是两个)。最初的iterable只在处理返回的迭代器之前最远的迭代器所需的范围内进行升级。你知道吗

下面是一个tee演示,其中一个生成器在生成值之前打印消息:

>>> import itertools
>>> def gen():
        for i in range(3):
            print("gen yielding {}".format(i))
            yield i


>>> a, b = itertools.tee(gen())
>>> next(a)
gen yielding 0
0
>>> next(a)
gen yielding 1
1
>>> next(b)
0
>>> next(b)
1
>>> next(b)
gen yielding 2
2
>>> next(b)
Traceback (most recent call last):
  File "<pyshell#245>", line 1, in <module>
    next(b)
StopIteration
>>> next(a)
2
>>> next(a)
Traceback (most recent call last):
  File "<pyshell#247>", line 1, in <module>
    next(a)
StopIteration

相关问题 更多 >