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?

## Solution 1

Here's a relevant example from the itertools module docs:

``````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, you need `itertools.izip` instead of `zip`:

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

One caveat: the `tee()` function produces two iterators that can advance independently of each other, but it comes at a cost. If one of the iterators advances further than the other, then `tee()` needs to keep the consumed elements in memory until the second iterator comsumes them too (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.

And since `tee()` can take an `n` parameter, this can also be used for more than two parallel iterators:

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

## Solution 2

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

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

## Solution 3

Im just putting this out, Im 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
``````

## Solution 4

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

## Solution 5

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.

## Solution 6

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

## Solution 7

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

## Solution 8

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

## Solution 9

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

## Solution 10

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

## Solution 11

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

## Solution 12

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