# How can I iterate over overlapping (current, next) pairs of values from a list?

## Question:

I sometimes need to iterate a list in Python looking at the "current" element and the "next" element. I have, till now, done so with code like:

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

This works and does what I expect, but is there’s a more idiomatic or efficient way to do the same thing?

Some answers to this problem can simplify by addressing the specific case of taking only two elements at a time. For the general case of N elements at a time, see Rolling or sliding window iterator?.

Since `the_list[1:]` actually creates a copy of the whole list (excluding its first element), and `zip()` creates a list of tuples immediately when called, in total three copies of your list are created. If your list is very large, you might prefer

``````from itertools import izip, islice
for current_item, next_item in izip(the_list, islice(the_list, 1, None)):
print(current_item, next_item)
``````

which does not copy the list at all.

The documentation for 3.8 provides this recipe:

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

For Python 2, use `itertools.izip` instead of `zip` to get the same kind of lazy iterator (`zip` will instead create a list):

``````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)
``````

How this works:

First, two parallel iterators, `a` and `b` are created (the `tee()` call), both pointing to the first element of the original iterable. The second iterator, `b` is moved 1 step forward (the `next(b, None)`) call). At this point `a` points to s0 and `b` points to s1. Both `a` and `b` can traverse the original iterator independently – the izip function takes the two iterators and makes pairs of the returned elements, advancing both iterators at the same pace.

Since `tee()` can take an `n` parameter (the number of iterators to produce), the same technique can be adapted to produce a larger "window". For example:

``````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)
``````

Caveat: If one of the iterators produced by `tee` advances further than the others, then the implementation needs to keep the consumed elements in memory until every iterator has consumed them (it cannot ‘rewind’ the original iterator). Here it doesn’t matter because one iterator is only 1 step ahead of the other, but in general it’s easy to use a lot of memory this way.

Iterating by index can do the same thing:

``````#!/usr/bin/python
the_list = [1, 2, 3, 4]
for i in xrange(len(the_list) - 1):
current_item, next_item = the_list[i], the_list[i + 1]
print(current_item, next_item)
``````

Output:

``````(1, 2)
(2, 3)
(3, 4)
``````

A basic solution:

``````def neighbors( list ):
i = 0
while i + 1 < len( list ):
yield ( list[ i ], list[ i + 1 ] )
i += 1

for ( x, y ) in neighbors( list ):
print( x, y )
``````
``````code = '0016364ee0942aa7cc04a8189ef3'
# Getting the current and next item
print  [code[idx]+code[idx+1] for idx in range(len(code)-1)]
# Getting the pair
print  [code[idx*2]+code[idx*2+1] for idx in range(len(code)/2)]
``````

Pairs from a list using a list comprehension

``````the_list = [1, 2, 3, 4]
pairs = [[the_list[i], the_list[i + 1]] for i in range(len(the_list) - 1)]
for [current_item, next_item] in pairs:
print(current_item, next_item)
``````

Output:

``````(1, 2)
(2, 3)
(3, 4)
``````

``````def pairwise(iterable):
it = iter(iterable)
a = next(it, None)

for b in it:
yield (a, b)
a = b
``````

I’m just putting this out, I’m very surprised no one has thought of enumerate().

``````for (index, thing) in enumerate(the_list):
if index < len(the_list):
current, next_ = thing, the_list[index + 1]
#do something
``````

I am really surprised nobody has mentioned the shorter, simpler and most importantly general solution:

Python 3:

``````from itertools import islice

def n_wise(iterable, n):
return zip(*(islice(iterable, i, None) for i in range(n)))
``````

Python 2:

``````from itertools import izip, islice

def n_wise(iterable, n):
return izip(*(islice(iterable, i, None) for i in xrange(n)))
``````

It works for pairwise iteration by passing `n=2`, but can handle any higher number:

``````>>> for a, b in n_wise('Hello!', 2):
>>>     print(a, b)
H e
e l
l l
l o
o !

>>> for a, b, c, d in n_wise('Hello World!', 4):
>>>     print(a, b, c, d)
H e l l
e l l o
l l o
l o   W
o   W o
W o r
W o r l
o r l d
r l d !
``````

This is now a simple Import As of 16th May 2020

``````from more_itertools import pairwise
for current, next in pairwise(your_iterable):
print(f'Current = {current}, next = {nxt}')
``````

Docs for more-itertools
Under the hood this code is the same as that in the other answers, but I much prefer imports when available.

If you don’t already have it installed then:
`pip install more-itertools`

Example

For instance if you had the fibbonnacci sequence, you could calculate the ratios of subsequent pairs as:

``````from more_itertools import pairwise
fib= [1,1,2,3,5,8,13]
for current, nxt in pairwise(fib):
ratio=current/nxt
print(f'Curent = {current}, next = {nxt}, ratio = {ratio} ')
``````

Starting in Python 3.10, this is the exact role of the `pairwise` function:

``````from itertools import pairwise

list(pairwise([1, 2, 3, 4, 5]))
# [(1, 2), (2, 3), (3, 4), (4, 5)]
``````

or simply `pairwise([1, 2, 3, 4, 5])` if you don’t need the result as a `list`.

As others have pointed out, `itertools.pairwise()` is the way to go on recent versions of Python. However, for 3.8+, a fun and somewhat more concise (compared to the other solutions that have been posted) option that does not require an extra import comes via the walrus operator:

``````def pairwise(iterable):
a = next(iterable)
yield from ((a, a := b) for b in iterable)
``````
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.