Few alternative solutions (other are possible), I usually use a variant of the first version, inside a partition function, the second variant is shorter when you don't have a handy partition() function and you don't want to import modules, and the forth one needs less memory when the data is very long:
from itertools import izip, islice
data = [1,2,3,4,5,6,7]
for x1, x2 in (data[i:i+2] for i in xrange(0, len(data)/2*2, 2)): print x1, x2
for x1, x2 in zip(data[::2], data[1::2]): print x1, x2
for x1, x2 in izip(data[::2], data[1::2]): print x1, x2
for x1, x2 in izip(islice(data,0,None,2), islice(data,1,None,2)): print x1, x2
>> I'm looking for a way to iterate through a list, two (or more) items >> at a time. Basically... >> >> myList = [1,2,3,4,5,6] >> >> I'd like to be able to pull out two items at a time...
Dan> def pair_list(list_): Dan> return [list_[i:i+2] for i in xrange(0, len(list_), 2)]
Here's another way (seems a bit clearer to me, but each person has their own way of seeing things):
Obviously, if your lists are long, you can substitute itertools.izip for zip. There's probably some easy way to achieve the same result with itertools.groupby, but I'm out of my experience there...
>I'd like to be able to pull out two items at a time - simple examples would >be: >Create this output: >1 2 >3 4 >5 6
b=iter(a) for x in b: y=b.next() print x,y
b=iter(a) for x,y in ((item, b.next()) for item in b): print x,y
>Create this list: >[(1,2), (3,4), (5,6)]
b=iter(a) [(item, b.next()) for item in b]
Note that they don't behave the same at the corner cases (empty list, single item, odd length...)
-- Gabriel Genellina Softlab SRL
__________________________________________________ Preguntá. Respondé. Descubrí. Todo lo que querías saber, y lo que ni imaginabas, está en Yahoo! Respuestas (Beta). ¡Probalo ya! http://www.yahoo.com.ar/respuestas
Thanks for all the fast responses. I'm particularly a fan of the zip method, followed closely by the xrange example. All, of course, are a lot of help! Thanks, Dave
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>]
> >>> [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>]
Wade Leftwich wrote: > 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>]
Note that all but the last of these generators are useless:
>>> chunks = [x for x in chunk(range(10), 3)] >>> [list(x) for x in chunks]
> > 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>]
> Note that all but the last of these generators are useless:
> >>> chunks = [x for x in chunk(range(10), 3)] > >>> [list(x) for x in chunks] > [[], [], [], [9]] # did you expect that? > In [48]: chunkgen = chunk(range(10), 3)
In [49]: for x in chunkgen: ....: print list(x) ....: ....: [0, 1, 2] [3, 4, 5] [6, 7, 8] [9]
> Peter
That's an interesting gotcha that I've never run into when using this function, because in practice I never put the generator returned by chunk() inside a list comprehension.
In [51]: chunkgen = chunk(range(10), 3)
In [52]: [list(x) for x in chunkgen] Out[52]: [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]
But, as you pointed out --
In [57]: chunkgen = chunk(range(10), 3)
In [58]: chunks = list(chunkgen)
In [59]: [list(x) for x in chunks] Out[59]: [[], [], [], [9]]
So apparently when we list(chunkgen), we are exhausting the generators that are its members. And if we do it again, we get rid of the [9] --
In [60]: [list(x) for x in chunks] Out[60]: [[], [], [], []]
I'll admit that chunk() is needlessly tricky for most purposes. I wrote it to accept a really lengthy, possibly unbounded, iterator and write out 10,000-line files from it, and also to play with Python's new functional capabilities.