小编典典

如何迭代列表中重叠的(当前,下一个)值对?

all

我有时需要在 Python 中迭代一个列表,查看“当前”元素和“下一个”元素。到目前为止,我已经使用如下代码完成了此操作:

for current, next in zip(the_list, the_list[1:]):
    # Do something

这有效并且符合我的期望,但是有没有更惯用或更有效的方法来做同样的事情?


阅读 64

收藏
2022-08-27

共1个答案

小编典典

这是来自itertools模块文档的相关示例:

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

对于 Python 2,您需要itertools.izip代替zip

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

这是如何工作的:

首先,创建了两个并行迭代器abtee()调用),它们都指向原始可迭代对象的第一个元素。第二个迭代器b向前移动了 1 步(next(b, None)调用)。此时指向as0又b指向s1。两者ab都可以独立地遍历原始迭代器 - izip
函数采用两个迭代器并生成成对的返回元素,以相同的速度推进两个迭代器。

一个警告:该tee()函数产生两个迭代器,它们可以相互独立地前进,但它是有代价的。如果其中一个迭代器比另一个更进一步,则tee()
需要将消耗的元素保留在内存中,直到第二个迭代器也使用它们(它不能“倒回”原始迭代器)。在这里没关系,因为一个迭代器只比另一个迭代器领先 1
步,但通常这种方式很容易使用大量内存。

并且由于tee()可以带一个n参数,这也可以用于两个以上的并行迭代器:

def threes(iterator):
    "s -> (s0, s1, s2), (s1, s2, s3), (s2, s3, 4), ..."
    a, b, c = itertools.tee(iterator, 3)
    next(b, None)
    next(c, None)
    next(c, None)
    return zip(a, b, c)
2022-08-27