# Iterating a sequence two items at a time

Discussion in 'Python' started by Ulrich Eckhardt, May 11, 2010.

1. ### Ulrich EckhardtGuest

Hi!

I have a list [1,2,3,4,5,6] which I'd like to iterate as (1,2), (3,4),
(5,6). I can of course roll my own, but I was wondering if there was

def as_pairs(seq):
i = iter(seq)
yield (i.next(), i.next())

Question to this code: Is the order of the "i.next()" calls guaranteed to be
from left to right? Or could I end up with pairs being switched?

Thanks!

Uli

--
Sator Laser GmbH
GeschÃ¤ftsfÃ¼hrer: Thorsten FÃ¶cking, Amtsgericht Hamburg HR B62 932

Ulrich Eckhardt, May 11, 2010

2. ### Chris RebertGuest

On Tue, May 11, 2010 at 12:09 AM, Ulrich Eckhardt
<> wrote:
> Hi!
>
> I have a list [1,2,3,4,5,6] which I'd like to iterate as (1,2), (3,4),
> (5,6). I can of course roll my own, but I was wondering if there was

When a problem involves iteration, always check the `itertools` module
in the std lib.
>From the module docs's recipe section

(http://docs.python.org/library/itertools.html#recipes):

import itertools
def grouper(n, iterable, fillvalue=None):
"grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
args = [iter(iterable)] * n
return itertools.izip_longest(fillvalue=fillvalue, *args)

>>> # Let's try it out.
>>> list(grouper(2, [1,2,3,4,5,6]))

[(1, 2), (3, 4), (5, 6)]
>>> # Success!

> def as_pairs(seq):
> Â  Â i = iter(seq)
> Â  Â yield (i.next(), i.next())
>
> Question to this code: Is the order of the "i.next()" calls guaranteed to be
> from left to right? Or could I end up with pairs being switched?

Pretty sure left-to-right is guaranteed; see http://bugs.python.org/issue448679
Also, if you're using Python 2.6+, the line should be:
yield (next(i), next(i))
See http://docs.python.org/library/functions.html#next

Cheers,
Chris
--
http://blog.rebertia.com

Chris Rebert, May 11, 2010

3. ### Bruno DesthuilliersGuest

> Hi!
>
> I have a list [1,2,3,4,5,6] which I'd like to iterate as (1,2), (3,4),
> (5,6). I can of course roll my own, but I was wondering if there was

>>> l = range(10)
>>> for x, y in zip(l[::2], l[1::2]):

.... print x, y
....
0 1
2 3
4 5
6 7
8 9

SimplestThingThatCouldPossiblyWork(tm) - but might not be the most
efficient idiom, specially with large lists...

Bruno Desthuilliers, May 11, 2010
4. ### Ulrich EckhardtGuest

Ulrich Eckhardt wrote:
> I have a list [1,2,3,4,5,6] which I'd like to iterate as (1,2), (3,4),
> (5,6). I can of course roll my own, but I was wondering if there was
>
>
> def as_pairs(seq):
> i = iter(seq)
> yield (i.next(), i.next())

Obviously this code does _not_ do what I want, it must be like this:

def as_pairs(seq):
i = iter(seq)
while True:
yield (i.next(), i.next())

Gah!

Uli

--
Sator Laser GmbH
GeschÃ¤ftsfÃ¼hrer: Thorsten FÃ¶cking, Amtsgericht Hamburg HR B62 932

Ulrich Eckhardt, May 11, 2010