Python for-loop超前

时间:2010-11-16 18:47:50

标签: python

我有一个python for循环,我需要向前看一个项目,看看在处理之前是否需要执行一个动作。

for line in file:
    if the start of the next line == "0":
        perform pre-processing
        ...
    continue with normal processing
    ...

有没有简单的方法在python中执行此操作? 我目前的方法是将文件缓冲到一个数组,但这并不理想,因为文件相当大。

8 个答案:

答案 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提到的pairwisewindowed工具。

# 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循环的第一次运行应该构建一个索引列表,您需要执行特殊操作。然后在第二次运行时,您可以将当前索引与列表进行比较,以确定是否需要执行该特殊操作。