2

阅读后如何将列表拆分为大小均匀的块?并且一直看到这种错误发生在https://code.djangoproject.com/ticket/18972上。

为什么chunkitertools 中没有函数?

编辑: grouper来自http://docs.python.org/2/library/itertools.html#recipes的行为与chunks

例子:

chunks([1, 2, 3, 4, 5], 3)
# Should return [[1, 2, 3], [4, 5]] or the iterator equivalent.
4

2 回答 2

4

在这里发布这样的问题并不是将这样的东西添加到 Python 中的方法。您也许应该尝试使用 Python 邮件列表。

chunks()用你要求的语义为你实现了。正确处理最后一个块有点棘手,但除此之外这很容易。如果将其添加到itertools它将用 C 编写,因此它会更快。

在 Python 2.6、Python 2.7 和 Python 3.2 中测试和工作。

import itertools as it
import sys

# use lazy xrange on 2.x; on 3.x plain "range" is always lazy
if sys.version_info[0] < 3:
    _range = xrange
else:
    _range = range

def chunks(iterable, n):
    """
    Yield up lists of n elements, taken from iterable.
    If length of iterable is not evenly divisible by n, the last list will be short.
    """
    if n < 1:
        raise ValueError("n must be >= 1")

    itr = iter(iterable)
    try:
        while True:
            lst = []
            for _ in _range(n):
                lst.append(next(itr))
            if not lst:
                break
            yield lst
    except StopIteration:
        # Only yield up a partial chunk if it is not zero length.
        if lst:
            yield lst

print(list(chunks([1, 2, 3, 4, 5, 6], 3)))  # prints: [[1, 2, 3], [4, 5, 6]]
print(list(chunks([1, 2, 3, 4, 5], 3))) # prints: [[1, 2, 3], [4, 5]]
print(list(chunks([], 3))) # prints: []
print(list(chunks([1, 2], 0))) # raises ValueError exception

编辑:

上述解决方案的低效率有点困扰我。我很确定必须有一个更简单的解决方案,itertools.islice()所以我想通了。我更喜欢这个。

def chunks(iterable, n):
    """
    Yield up lists of n elements, taken from iterable.
    If length of iterable is not evenly divisible by n, the last list will be short.
    """
    if n < 1:
        raise ValueError("n must be >= 1")

    itr = iter(iterable)

    while True:
        lst = list(it.islice(itr, n))
        if not lst:
            break
        yield lst
于 2013-05-01T06:06:26.867 回答
2

它不在 itertools 中,但在 itertools 的页面上提到了它作为配方:

http://docs.python.org/2/library/itertools.html#recipes

def grouper(n, iterable, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

您不妨问为什么所有其他食谱都没有包含在 itertools 中:)

于 2013-05-01T05:08:32.300 回答