成对遍历列表或元组

时间:2010-10-03 11:57:48

标签: python iteration

a = [5, 66, 7, 8, 9, ...]

是否可以进行迭代而不是像这样写?

a[1] - a[0]

a[2] - a[1]

a[3] - a[2]

a[4] - a[3]

...

谢谢!

6 个答案:

答案 0 :(得分:47)

使用range完全没问题。然而,编程(如数学)是建立在抽象的基础上。连续对 [(x0,x1),(x1,x2),...,(xn-2,xn-1)] 被称为成对组合,请参阅例如recipe in the itertools docs。在工具集中使用此功能后,您可以编写:

for x, y in pairwise(xs):
    print(y - x)

或者,作为生成器表达式:

consecutive_diffs = (y - x for (x, y) in pairwise(xs))

答案 1 :(得分:17)

对于python 2中的小列表或python 3中的任何列表,您可以使用

[x - y for x, y in zip(a[1:], a)]

对于更大的列表,您可能需要

import itertools as it

[x - y for x, y in it.izip(a[1:], a)]

如果您使用的是python 2

我会考虑将其写为生成器表达式而不是

(x - y for x, y in it.izip(a[1:], a))

这将避免一次性在内存中创建第二个列表,但您只能迭代一次。如果你只想迭代它一次,那么这是理想的,如果你以后决定需要随机或重复访问,这很容易改变。特别是如果您要进一步处理它以制作列表,那么最后一个选项是理想的。

更新

目前最快的方法是

import itertools as it
import operator as op

list(it.starmap(op.sub, it.izip(a[1:], a)))

$ python -mtimeit -s's = [1, 2]*10000' '[x - y for x, y in zip(s[1:], s)]'
100 loops, best of 3: 13.5 msec per loop

$ python -mtimeit -s'import itertools as it; s = [1, 2]*10000' '[x - y for x, y in it.izip(s[1:], s)]'
100 loops, best of 3: 8.4 msec per loop

$ python -mtimeit -s'import itertools as it; import operator as op; s = [1, 2]*10000' 'list(it.starmap(op.sub, it.izip(s[1:], s)))'
100 loops, best of 3: 6.38 msec per loop

答案 2 :(得分:5)

不确定

for i in range(1, len(a)):
    print a[i] - a[i-1]

我看不出真正的问题在这里。你看过the python tutorial吗?

答案 3 :(得分:0)

以下是itertools reciepes的示例:

from itertools import tee

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

哪个不太可读。如果你喜欢更容易理解的东西 了解生成器如何工作,这里有一个更长的例子,结果相同:

def pairwise(it):
    """
    Walk a list in overlapping pairs.

    >>> list(pairwise([0, 1, 2, 3, 4, 5]))
    [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
    """
    it = iter(it)
    start = None
    while True:
        if not start:
            start = next(it)
        end = next(it)
        yield start, end
        start = end

答案 4 :(得分:0)

def pairwise(iterable):
    i = iter(iterable)
    while True:
        yield next(i), next(i, '')

答案 5 :(得分:0)

我建议使用很棒的more_itertools库,它具有立即可用的pairwise function

import more_itertools

for a, b in more_itertools.pairwise([1, 2, 3, 4, 5]):
    print(a, b)
# 1 2
# 2 3
# 3 4
# 4 5

这将使您免于编写自己的(可能有错误的)实现的麻烦。例如,此页面上的大多数实现都无法正确处理带有空的Iterable的情况-生成器函数永远不应引发StopIteration,此行为considered deprecated并在Python 3.6中引起DeprecationWarning。它根本无法在Python 3.7中使用。