36

Possible Duplicate:
Python - Differences between elements of a list

I have a list and I want to find difference between consecutive elements:

a = [0, 4, 10, 100]
find_diff(a)
>>> [4,6,90]

How would you code find_diff() function? I can code this with "for" iterator but I am sure there are very simple ways to do it with a simple one liner.

Community
  • 1
  • 1
gok
  • 1,137
  • 1
  • 9
  • 30
  • hmm, I was going to accept the first answer but I see that it is deleted now. – gok Mar 15 '11 at 15:57
  • As well it should have been, since that question asks **exactly the same thing**. – Matt Ball Mar 15 '11 at 15:58
  • so should I delete this question? I couldn't find that one in search before asking – gok Mar 15 '11 at 15:59
  • 2
    Don't delete it. This will get closed as a dup, so no more answers can be added. In general, it's good to have multiple dups which point to a single, canonical Q&A. Since there is more than one way to word a question, having multiple (differently-worded) questions pointing to a master Q&A makes it easier to find the master in the future. – Matt Ball Mar 15 '11 at 16:01

3 Answers3

78

You could utilize enumerate, zip and list comprehensions:

>>> a = [0, 4, 10, 100]

# basic enumerate without condition:
>>> [x - a[i - 1] for i, x in enumerate(a)][1:]
[4, 6, 90]

# enumerate with conditional inside the list comprehension:
>>> [x - a[i - 1] for i, x in enumerate(a) if i > 0]
[4, 6, 90]

# the zip version seems more concise and elegant:
>>> [t - s for s, t in zip(a, a[1:])]
[4, 6, 90]

Performance-wise, there seems to be not too much variance:

In [5]: %timeit [x - a[i - 1] for i, x in enumerate(a)][1:]
1000000 loops, best of 3: 1.34 µs per loop

In [6]: %timeit [x - a[i - 1] for i, x in enumerate(a) if i > 0]
1000000 loops, best of 3: 1.11 µs per loop

In [7]: %timeit [t - s for s, t in zip(a, a[1:])]
1000000 loops, best of 3: 1.1 µs per loop
miku
  • 181,842
  • 47
  • 306
  • 310
18

Use itertools.pairwise (Python 3.10+):

>>> from itertools import pairwise
>>> a = [0, 4, 10, 100]
>>> [y - x for x, y in pairwise(a)]
[4, 6, 90]

For Python 3.9 and older you can use the recipe for pairwise from the itertools documentation:

from itertools import izip, tee
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return izip(a, b)
Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
  • 1
    That's completely unnecessary. See [Python - Differences between elements of a list](http://stackoverflow.com/questions/2400840/python-differences-between-elements-of-a-list). – Matt Ball Mar 15 '11 at 15:59
  • 15
    @Matt Ball: Many iterators can be called "unnecessary", but once defined, they're darn useful for common idioms. Why ask the reader to puzzle out a zip of two slices when we can assign a useful name to the idea like `pairwise`. I don't think I'm alone in thinking this as I lifted the example directly from the docs. – Steven Rumbalski Mar 15 '11 at 16:13
  • 1
    +! This version works for arbitrary generators, which can't be sliced/indexed. – avmohan Sep 04 '17 at 15:55
  • 1
    This function is available in itertools Python 3.10 and above – arjunsiva Dec 26 '22 at 06:45
6
[x - a[i-1] if i else None for i, x in enumerate(a)][1:]
kindall
  • 178,883
  • 35
  • 278
  • 309