How to chunk a list in Python 3?
I found the following 开发者_开发百科code that is compatible with python2
from itertools import izip_longest
def grouper(n, iterable, padvalue=None):
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
return izip_longest(*[iter(iterable)]*n, fillvalue=padvalue)
However, this isn't working with Python 3. I get the following error
ImportError: cannot import name izip_longest
Can someone help?
I'd like to convert my list of [1,2,3,4,5,6,7,8,9]
to [[1,2,3],[4,5,6],[7,8,9]]
Edit
Now Python3 compatible
Code below is adapted from the selected answer. Simply change name from izip_longest
to zip_longest
.
from itertools import zip_longest
def grouper(n, iterable, padvalue=None):
"grouper(3, 'abcdefg', 'x') --> ('a','b','c'), ('d','e','f'), ('g','x','x')"
return zip_longest(*[iter(iterable)]*n, fillvalue=padvalue)
In Python 3's itertools
there is a function called zip_longest
. It should do the same as izip_longest
from Python 2.
Why the change in name? You might also notice that itertools.izip
is now gone in Python 3 - that's because in Python 3, the zip
built-in function now returns an iterator, whereas in Python 2 it returns a list. Since there's no need for the izip
function, it also makes sense to rename the _longest
variant for consistency.
After all that discussion above, here's a python3 solution that I believe gives safer, more predicable results.
def chunker(iter, size):
chunks = [];
if size < 1:
raise ValueError('Chunk size must be greater than 0.')
for i in range(0, len(iter), size):
chunks.append(iter[i:(i+size)])
return chunks
example = [1,2,3,4,5,6,7,8,9]
print(' 1: ' + str(chunker(example, 1)))
print(' 3: ' + str(chunker(example, 3)))
print(' 4: ' + str(chunker(example, 4)))
print(' 8: ' + str(chunker(example, 8)))
print(' 9: ' + str(chunker(example, 9)))
print('10: ' + str(chunker(example, 10)))
The results are:
$ python3 iter_chunk.py
1: [[1], [2], [3], [4], [5], [6], [7], [8], [9]]
3: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
4: [[1, 2, 3, 4], [5, 6, 7, 8], [9]]
8: [[1, 2, 3, 4, 5, 6, 7, 8], [9]]
9: [[1, 2, 3, 4, 5, 6, 7, 8, 9]]
10: [[1, 2, 3, 4, 5, 6, 7, 8, 9]]
According to the doc:
>>> s = [1,2,3,4,5,6,7,8,9]
>>> n = 3
>>> list(zip(*[iter(s)]*n))
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
s = [1,2,3,4,5,6,7,8,9]
size = 4
chuck_list = [s[i:i+size] for i in range(0, len(s), size)]
The source code of the grouper()
function included in the question is copied from the documentation for itertools
, more specifically the section Itertools Recipes.
In this documentation, it is stated that:
This section shows recipes for creating an extended toolset using the existing
itertools
as building blocks.Substantially all of these recipes and many, many others can be installed from the
more-itertools
project found on the Python Package Index:pip install more-itertools
If you look at the documentation of the more-itertools
package, then you will notice that the objective pursued in the question, i.e. to chunk a list, could be achieved with the following functions present in this package:
sliced()
to yield a list from sliceable iterables,chunked()
to yield a list from non-sliceable iterables.ichunked()
to yield iterables instead of lists.
For many readers who would land on this page, as they are looking for a solution which fulfills this objective, this packages offers several advantages: i) code is always up-to-date, ii) many other useful functions are present.
精彩评论