[Python-Dev] Proposal: new list function: pack
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():
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
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.
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