pairwise traversal of a list or tuple

2019-01-14 22:49发布

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

Is it possible to make an iteration instead of writing like this?

a[1] - a[0]

a[2] - a[1]

a[3] - a[2]

a[4] - a[3]

...

Thank you!

5条回答
三岁会撩人
2楼-- · 2019-01-14 23:25

for a small list in python 2 or any list in python 3, you can use

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

for a larger list, you probably want

import itertools as it

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

if you are using python 2

And I would consider writing it as a generator expression instead

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

This will avoid creating the second list in memory all at once but you will only be able to iterate over it once. If you only want to iterate over it once, then this is ideal and it's easy enough to change if you decide later that you need random or repeated access. In particular if you were going to further process it to make a list, then this last option is ideal.

update:

The fastest method by far is

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
查看更多
趁早两清
3楼-- · 2019-01-14 23:34
def pairwise(iterable):
    i = iter(iterable)
    while True:
        yield next(i), next(i, '')
查看更多
三岁会撩人
4楼-- · 2019-01-14 23:35

Here is the example from the 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)

Which is not very readable.If you prefer something more understandable and understand how generators work, here a bit longer example with the same result:

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
查看更多
再贱就再见
5楼-- · 2019-01-14 23:38

Using range is perfectly fine. However, programming (like maths) is about building on abstractions. Consecutive pairs [(x0, x1), (x1, x2), ..., (xn-2, xn-1)], are called pairwise combinations, see for example a recipe in the itertools docs. Once you have this function in your toolset, you can write:

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

Or, as a generator expression:

consecutive_diffs = (y - x for (x, y) in pairwise(xs))
查看更多
Explosion°爆炸
6楼-- · 2019-01-14 23:43

Sure.

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

I fail to see what the real problem is here. Have you read the python tutorial?

查看更多
登录 后发表回答