用Python中的两个单元格从文件中读取行作为移位寄存器
我需要读取一个文件的行,这样的方式将表现为两个单元的移位寄存器。 例如:用Python中的两个单元格从文件中读取行作为移位寄存器,python,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 = lin
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....
可以在打开(文件'r')
的情况下执行此操作,但不能保证在脚本可能停止时关闭文件
由于在最后一次迭代之前“做点什么”的原因
有什么优雅的方法吗?当然可以:
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
蒂姆的回答很好。“爱好者”解决方案是使用
itertools.tee
使用pairwise
配方,如图所示:
tee
是一个非常简洁的函数。它可以在任何时候使用,你想在同一个iterable上迭代多次。如果您或多或少地并行使用所有迭代器(而不是运行一个迭代直到完成,然后再执行下一个迭代等等),那么它比将整个iterable转储到列表
或可以反复迭代的其他容器中更节省空间
基本上,您向它传递一个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
导入itertools
>>>def gen():
对于范围(3)中的i:
打印(格式(i))
产量一
>>>a,b=itertools.tee(gen())
>>>下一(a)
产生0
0
>>>下一(a)
第1代
1.
>>>下一(b)
0
>>>下一(b)
1.
>>>下一(b)
第2代
2.
>>>下一(b)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
下一(b)
停止迭代
>>>下一(a)
2.
>>>下一(a)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
下一(a)
停止迭代
和都很好。要添加到解决方案池中,还可以使用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
中的值,则上述实现将生成一个空生成器,谢谢!就在钱上!:)@Blckknght:我查看了itertools
中的tee
函数,但无法理解它。你能解释一下你的解决方案是如何工作的吗?@弗拉门戈:我在我的答案中添加了一个关于tee
的解释。你不需要知道实现的细节就能理解它的功能。@Blckknght:这很好!谢谢你花时间解释!也许我不明白,但是如果程序出于某种原因退出,用块打开一个文件可以保证该文件将被关闭。@Joel:是的,如果打开(…)
文件将被关闭,但我指的是它可以作为f=open(…)打开的情况
然后需要手动关闭。这是在得到你们的帮助之前。谢谢明白了。顺便说一句,使用open(…)执行
相当于执行try:f=open(…);最后:f.close()
。@Joel:我也喜欢窗口化的想法。所有答案都很好。我学了一些新东西。谢谢大家!@弗拉门戈:那么,别忘了对所有答案进行投票。如果答案对你更合适的话,不要犹豫,接受一个不同的答案。@Tim:好了!如果可以的话,我会接受他们所有人,因为他们都平等地给了我带回家的东西。我有件事要告诉你们——看看我刚刚发布的这个问题:用什么样的pythonic方式来模拟与外部设备的通信?RPyC?
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)