kjo - 8 months ago 29

Python Question

In Python, it is easy to break an *n*-long list into *k*-size chunks if *n* is a multiple of *k* (IOW,

`n % k == 0`

`>>> k = 3`

>>> n = 5 * k

>>> x = range(k * 5)

>>> zip(*[iter(x)] * k)

[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]

(The trick is that

`[iter(x)] * k`

`iter(x)`

`zip`

`*`

`[iter(x)] * k`

`zip`

The main shortcoming I see with this idiom is that, when

`n % k > 0`

`>>> zip(*[iter(x)] * (k + 1))`

[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)]

There's an alternative idiom that is slightly longer to type, produces the same result as the one above when

`n % k == 0`

`n % k > 0`

`>>> map(None, *[iter(x)] * k)`

[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]

>>> map(None, *[iter(x)] * (k + 1))

[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14, None)]

At least, here the left over entries are retained, but the last chunk gets padded with

`None`

`itertools.izip_longest`

But suppose the desired solution is one in which the last chunk is left unpadded, i.e.

`[(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11), (12, 13, 14)]`

Is there a

`map(None, *[iter(x)]*k)`

(Granted, it is not difficult to solve this problem by writing a function (see, for example, the many fine replies to How do you split a list into evenly sized chunks in Python? or What is the most "pythonic" way to iterate over a list in chunks?). Therefore, a more accurate title for this question would be "How to salvage the

`map(None, *[iter(x)]*k)`

I was struck by how easy it is to break a list into even-sized chunks, and how difficult (