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

Roll your own!

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