我有一个python for循环,我需要向前看一个项目,看看在处理之前是否需要执行一个动作。
for line in file:
if the start of the next line == "0":
perform pre-processing
...
continue with normal processing
...
有没有简单的方法在python中执行此操作? 我目前的方法是将文件缓冲到一个数组,但这并不理想,因为文件相当大。
答案 0 :(得分:17)
您可以使用此配方获取任何可迭代的预取下一个项目:
from itertools import tee, islice, izip_longest
def get_next(some_iterable, window=1):
items, nexts = tee(some_iterable, 2)
nexts = islice(nexts, window, None)
return izip_longest(items, nexts)
使用示例:
for line, next_line in get_next(myfile):
if next_line and next_line.startswith("0"):
... do stuff
如果您想要查看2行或更多行,则代码允许您将window
参数作为较大的值传递。
答案 1 :(得分:9)
您可以在prev_line
处存储上一行,并在您根据条件阅读一行时处理该行。
类似的东西:
prev_line = None
for line in file:
if prev_line is not None and the start of the next line == "0":
perform pre-processing on prev_line
...
continue with normal processing
...
prev_line = line
如有必要,您可能需要对最后一行进行其他处理,具体取决于您的逻辑。
答案 2 :(得分:8)
根据nosklo的回答,我倾向于使用以下模式:
优秀itertools recipes中的函数pairwise
非常适用于此:
from itertools import tee
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
next(b, None)
return izip(a, b)
在代码中使用它可以获取:
for line, next_line in pairwise(file):
if next_line.startswith("0"):
pass #perform pre-processing
#...
pass #continue with normal processing
通常,对于这种类型的处理(可迭代中的前瞻),我倾向于使用window function。 Pairwise是一个大小为2的窗口的特殊情况。
答案 3 :(得分:3)
你只需要缓冲一行。
for line in file:
if (prevLine is not None):
//test line as look ahead and then act on prevLine
prevLine = line
答案 4 :(得分:2)
这也应该有用。我总是更喜欢在第一轮中设置next
而不是设置something = None
。
prev_line = next(the_file)
for current_line in the_file:
if current_line.startswith('0'):
do_stuff( prev_line )
# continue with normal processing
# ...
prev_line = current_line
答案 5 :(得分:1)
more_itertools
有几个lookahead tools。在这里,我们将演示一些用于处理文件行的工具和抽象函数。给出:
f = """\
A
B
C
0
D\
"""
lines = f.splitlines()
代码
import more_itertools as mit
def iter_lookahead(iterable, pred):
# Option 1
p = mit.peekable(iterable)
try:
while True:
line = next(p)
next_line = p.peek()
if pred(next_line):
# Do something
pass
else:
print(line)
except StopIteration:
return
pred = lambda x: x.startswith("0")
iter_lookahead(lines, pred)
输出
A
B
0
以下是使用同一个库的其他选项,其中包含@Muhammad Alkarouri提到的pairwise
和windowed
工具。
# Option 2
for line, next_line in mit.pairwise(lines):
if pred(next_line):
# Do something
pass
else:
print(line)
# Option 3
for line, next_line in mit.windowed(lines, 2):
if pred(next_line):
# Do something
pass
else:
print(line)
后面的选项可以独立运行,也可以替换先前函数中的逻辑。
答案 6 :(得分:1)
比这一切都容易得多...
lines = len(file)
for i in range(0,lines):
current_line = file[i]
if i < lines - 1:
next_line = file[i + 1]
else:
next_line = None
do_your_work(current_line,next_line)
答案 7 :(得分:-3)
我不是Python专家,但我想你需要使用2个循环。 for循环的第一次运行应该构建一个索引列表,您需要执行特殊操作。然后在第二次运行时,您可以将当前索引与列表进行比较,以确定是否需要执行该特殊操作。