【问题标题】:How to chunk a list in Python 3?如何在 Python 3 中对列表进行分块?
【发布时间】:2011-08-16 13:42:21
【问题描述】:

我找到了以下与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)

但是,这不适用于 Python 3。我收到以下错误

ImportError: cannot import name izip_longest

有人可以帮忙吗?

我想将我的[1,2,3,4,5,6,7,8,9] 列表转换为[[1,2,3],[4,5,6],[7,8,9]]

编辑

现在兼容 Python3

以下代码改编自所选答案。只需将名称从 izip_longest 更改为 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)

【问题讨论】:

标签: python list python-3.x


【解决方案1】:

在 Python 3 的 itertools 中有一个名为 zip_longest 的函数。它应该与 Python 2 中的 izip_longest 相同。

为什么要改名?您可能还注意到 itertools.izip 现在在 Python 3 中消失了——这是因为在 Python 3 中,zip 内置函数现在返回一个迭代器,而在 Python 2 中它返回一个列表。由于不需要 izip 函数,因此重命名 _longest 变体以保持一致性也是有意义的。

【讨论】:

    【解决方案2】:

    根据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)]
    

    【讨论】:

    • 请注意,len(s) % n != 0 将导致缺少成员,因为给定的配方不处理剩余部分。例如,n = 8 将导致 [(1, 2, 3, 4), (5, 6, 7, 8)]。 9在哪里?同样,:n > len(s) 将导致 []
    • 必要时可以将 zip 替换为 itertools.zip_longest。
    • 使用n = 8 和itertools.zip_longest,我们得到[(1, 2, 3, 4), (5, 6, 7, 8), (9, None, None, None)]。我们确实找回了 9,但现在您必须减轻 Nones。而且,对于n > len(s),我们还剩下[]。 PHP 对array_chunk() 的实现似乎总是很直观,在n = 8[(1, 2, 3, 4), (5, 6, 7, 8), (9)]n > len(s) 中,您可以返回(用Python 的说法),而对于n > len(s),您将返回原始数组作为外部数组的唯一成员。这样你总能得到一些你可以安全地通过两个嵌套循环而没有太多警告的东西。
    • @JasonGabler:zip_longest 有一个fillvalue 关键字参数,允许您指定除None 之外的填充值。
    【解决方案3】:

    经过以上所有讨论,我相信这是一个 python3 解决方案,它可以提供更安全、更可预测的结果。

    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)))
    

    结果是:

    $ 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]]
    

    【讨论】:

      【解决方案4】:

      问题中包含的grouper() 函数的源代码是从itertools 的文档中复制的,更具体地说是Itertools Recipes 部分。

      在本文档中,声明:

      本部分展示了使用现有 itertools 作为构建块创建扩展工具集的方法。

      几乎所有这些配方以及许多其他配方都可以从more-itertools 项目found on the Python Package Index 安装:

      pip install more-itertools
      

      如果您查看the documentation of the more-itertools package,那么您会注意到问题中追求的目标,即分块列表,可以通过此包中提供的以下功能来实现:

      • sliced() 从可切片的迭代中产生一个列表,
      • chunked() 从不可切片的迭代中产生一个列表。
      • ichunked() 产生迭代而不是列表。

      对于许多将登陆此页面的读者,因为他们正在寻找实现此目标的解决方案,此软件包提供了几个优点:i)代码始终是最新的,ii)存在许多其他有用的功能.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-27
        • 1970-01-01
        相关资源
        最近更新 更多