Iterate through list two items at a time

Wade Leftwich wleftwich at gmail.com
Thu Jan 4 07:33:00 EST 2007


Wade Leftwich wrote:
> Jeffrey Froman wrote:
> > Dave Dean wrote:
> >
> > >  I'm looking for a way to iterate through a list, two (or more) items at a
> > > time.
> >
> > Here's a solution, from the iterools documentation. It may not be the /most/
> > beautiful, but it is short, and scales well for larger groupings:
> >
> > >>> from itertools import izip
> > >>> def groupn(iterable, n):
> > ...     return izip(* [iter(iterable)] * n)
> > ...
> > >>> list(groupn(myList, 2))
> > [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, 11)]
> > >>> list(groupn(myList, 3))
> > [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)]
> > >>> list(groupn(myList, 4))
> > [(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)]
> > >>> for a,b in groupn(myList, 2):
> > ...     print a, b
> > ...
> > 0 1
> > 2 3
> > 4 5
> > 6 7
> > 8 9
> > 10 11
> > >>>
> >
> > Jeffrey
>
> This works great except you lose any 'remainder' from myList:
>
> >>> list(groupn(range(10),3))
> [(0, 1, 2), (3, 4, 5), (6, 7, 8)]  # did not include (9,)
>
> The following might be more complex than necessary but it solves the
> problem, and like groupn()
> it works on infinite lists.
>
> from itertools import groupby, imap
> def chunk(it, n=0):
>     if n == 0:
>         return iter([it])
>     grouped = groupby(enumerate(it), lambda x: int(x[0]/n))
>     counted = imap(lambda x:x[1], grouped)
>     return imap(lambda x: imap(lambda y: y[1], x), counted)
>
> >>> [list(x) for x in chunk(range(10), 3)]
> [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
>
> Note the chunks are iterators, not tuples as in groupn():
>
> >>> [x for x in chunk(range(10), 3)]
> [<itertools.imap object at 0xb78d4c4c>,
>  <itertools.imap object at 0xb78d806c>,
>  <itertools.imap object at 0xb78d808c>,
>  <itertools.imap object at 0xb78d4c6c>]
>
>
> -- Wade Leftwich
> Ithaca, NY

Or, using generator expressions instead of imap and getting rid of the
lambdas --

from itertools import groupby

def chunk(it, n=0):
    if n == 0:
        return iter([it])
    def groupfun((x,y)):
        return int(x/n)
    grouped = groupby(enumerate(it), groupfun)
    counted = (y for (x,y) in grouped)
    return ((z for (y,z) in x) for x in counted)

>>> [list(x) for x in chunk(range(10), 3)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

>>> [x for x in chunk(range(10), 3)]
[<generator object at 0xb7a34e4c>,
 <generator object at 0xb7a34dac>,
 <generator object at 0xb7a34d2c>,
 <generator object at 0xb7a34d6c>]




More information about the Python-list mailing list