145

Is it possible to iterate a list in the following way in Python (treat this code as pseudocode)?

a = [5, 7, 11, 4, 5]
for v, w in a:
    print [v, w]

And it should produce

[5, 7]
[7, 11]
[11, 4]
[4, 5]
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
marvin_yorke
  • 3,469
  • 4
  • 25
  • 35

6 Answers6

214

You can zip the list with itself sans the first element:

a = [5, 7, 11, 4, 5]

for previous, current in zip(a, a[1:]):
    print(previous, current)

This works even if your list has no elements or only 1 element (in which case zip returns an empty iterable and the code in the for loop never executes). It doesn't work on generators, only sequences (tuple, list, str, etc).

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
hluk
  • 5,848
  • 2
  • 21
  • 19
  • 4
    This does not work. Each of the separate lists you are iterating do not sufficiently "skip" the next record, so your example gives output like:[5, 7] [7, 11] [11, 4] [4, 5] – Brad Mar 05 '14 at 15:03
  • 17
    But that's exactly the result we want, isn't it? – hluk Mar 06 '14 at 06:46
  • 5
    Hmm...yea - I think the OP was looking for it - though I saw "pairwise" iteration as returning like [5,7], [11,4], [5,None] – Brad Mar 06 '14 at 19:29
  • 42
    @Brad For this case, `zip(a[::2], a[1::2])`, which will step by 2 through each list. – Evgeni Sergeev Mar 19 '15 at 06:09
123

From the itertools recipes:

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)

for v, w in pairwise(a):
    ...
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
  • Nice, but is not this overkilling?. What is the advantage of your approach relative to the simple for-loop in the answer from SanSS? I timed both and the speed was very similar (itertools wins by ca 10%, no big deal) – joaquin Apr 23 '11 at 19:02
  • 5
    @joaquin: The difference is that it works on iterators, not just sequences. That's not needed here, but you can hardly call that overkill. I just prefer iterators because I work with them all the time. – Jochen Ritzel Apr 23 '11 at 20:32
  • 5
    For anyone interested in circular pairs from e.g. a list `a`, just do: `pairwise(a +[a[0] ] )`. – 0 _ Dec 11 '13 at 23:57
  • 7
    Note to those finding this, the advantage that this works on iterators is that this does not require random access into a stream of data (i.e. array access); rather, it only needs to ingest each item once, and caches it for the next evaluation. So if you have, say, a Twitter firehose, you don't ever need to read the firehose into a gigantic (perhaps infinite-length) array for this to work. – btown Jan 16 '14 at 22:13
  • 1
    This solution does not drop last element if iterable cardinality is odd VS zip. – user305883 Oct 04 '16 at 18:26
  • 1
    In Python 3, you will get `ImportError: cannot import name 'izip' from 'itertools' (unknown location)`. You can just use `zip` instead of `izip` from itertools in Python 3. – josch Jul 06 '19 at 07:37
  • @IoannisFilippidis In python3 where only `zip_longest` exists in itertools, I got it working like this: `zip_longest(a, b, fillvalue=iterable[0])`. Else, I would get an additional tupel of `(a[0], None)` as the last output if I used `pairwise(a +[a[0] ] )` I did not test if my approach works for any type of iterable though, my input is a list and it works for lists. – ElectRocnic Jun 05 '20 at 09:58
  • The last tuple in `list(pairwise(a + [a[0]])` is `(a[-1], a[0])`. – 0 _ Jun 05 '20 at 10:26
  • 6
    In Python 3.10, you can use `itertools.pairwise`: https://docs.python.org/3/library/itertools.html#itertools.pairwise – nimble_ninja Mar 20 '22 at 21:23
61

To do that you should do:

a =  [5, 7, 11, 4, 5]
for i in range(len(a)-1):
    print [a[i], a[i+1]]
Santiago Alessandri
  • 6,630
  • 30
  • 46
  • 4
    Referencing a list item by index is something of an anti-pattern in Python (except when the items must be access out-of-sequence). See https://github.com/JeffPaine/beautiful_idiomatic_python#looping-over-a-collection – Ian Goldby Jan 13 '20 at 13:16
18

Nearly verbatim from Iterate over pairs in a list (circular fashion) in Python:

def pairs(seq):
    i = iter(seq)
    prev = next(i)
    for item in i:
        yield prev, item
        prev = item
ideasman42
  • 42,413
  • 44
  • 197
  • 320
Gabe
  • 84,912
  • 12
  • 139
  • 238
7
>>> a = [5, 7, 11, 4, 5]
>>> for n,k in enumerate(a[:-1]):
...     print a[n],a[n+1]
...
5 7
7 11
11 4
4 5
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
5

An alternative way is itertools.pairwise (Python 3.10 or later):

from itertools import pairwise

temp = [-39.5, -27.5, -15.5, -3.5, 8.5, 20.5, 32.5, 44.5, 56.5, 68.5, 80.5, 92.5,104.5]
res = list(pairwise(temp))

[(-39.5, -27.5), (-27.5, -15.5), (-15.5, -3.5), (-3.5, 8.5), (8.5, 20.5), (20.5, 32.5), (32.5, 44.5), (44.5, 56.5), (56.5, 68.5), (68.5, 80.5), (80.5, 92.5), (92.5, 104.5)]
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
RomanPerekhrest
  • 88,541
  • 4
  • 65
  • 105