[Python-Dev] Proposal: new list function: pack

Hrvoje Niksic hrvoje.niksic at avl.com
Fri Mar 20 16:37:13 CET 2009

Isaac Morland wrote:
>> I propose this because i need a lot of times pack and slide function
>> over list and this one
>> combine the two in a generator way.

I've written functions with a subset of this functionality on more than 
one occasion.  Having it in itertools looks like it would be useful to a 
lot of people.

> See the Python documentation for zip():
> http://docs.python.org/library/functions.html#zip

zip can be used to achieve this purpose, but only with serious 
itertools-fu.  If I want to iterate over a list [1, 2, 3, 4] looking at 
pairs (1, 2) and (3, 4), it would be much nicer to write:

for a, b in itertools.pack(l, 2):


for a, b in itertools.izip(*[iter(l)]*2):

which is what the zip documentation proposes.  The former would be clear 
to anyone looking at the documentation of "pack" (and maybe even without 
it if we choose a better name), while the latter requires quite some 
deciphering, followed by carefully looking at izip's documentation that 
it's actually legal to rely on argument evaluation order and not peeking 
at iterables, like that code does.

izip is not the only contender for this pattern; something similar is 
possible using groupby, but it's hard to make it fit in an easily 
understable line either.  This is the shortest I came up with:

def pack(iterable, n):
     cycler = (i for i in itertools.count() for j in xrange(n))
     return (g for k, g in
             itertools.groupby(iterable, lambda x: cycler.next()))

This has the nice property that it returns iterables rather than tuples, 
although tuples are probably good enough (they seem to be good enough 
for izip).

The name "pack" is a bit too cryptic, even by itertools standards, so it 
might be better to choose a name that conveys the intention of returning 
"groups of n adjacent elements" (group_adjacent?).  To fit with the rest 
of itertools, and to be really useful, the function shouldn't insist on 
sequences, but should accept any iterable.

> http://drj11.wordpress.com/2009/01/28/my-python-dream-about-groups/

That posting ends with:

It still scares me a bit.
This code is obviously ridiculous. I can’t help feeling I’ve missed a 
more Pythonic way of doing it.

Looking at izip(*[iter(l)]*n), I tend to agree.

More information about the Python-Dev mailing list