开发者

How to chunk a list in Python 3?

开发者 https://www.devze.com 2023-03-02 16:48 出处:网络
I found the following 开发者_开发百科code that is compatible with python2 from itertools import izip_longest

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消