Python 3 生成器理解生成 block ,包括最后

标签 python python-3.x generator

如果您在 Python 3.7 中有一个列表:

>>> li
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

您可以使用两个常见的 Python 习语之一将其转换为每个长度为 n 的 block 列表:

>>> n=3
>>> list(zip(*[iter(li)]*n))
[(0, 1, 2), (3, 4, 5), (6, 7, 8)]

由于 (9,10) 的长度不是 n

,所以删除最后一个不完整的元组

您还可以:

>>> [li[i:i+n] for i in range(0,len(li),n)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]

如果你想要最后一个子列表,即使它少于 n 个元素。

假设现在我有一个生成器,gen,未知长度或终止(因此调用 list(gen))sum(1 for _ in gen) 不明智)我想要每个 block 。

我能想出的最好的生成器表达式是这样的:

from itertools import zip_longest
sentinel=object()             # for use in filtering out ending chunks
gen=(e for e in range(22))    # fill in for the actual gen

g3=(t if sentinel not in t else tuple(filter(lambda x: x != sentinel, t)) for t in zip_longest(*[iter(gen)]*n,fillvalue=sentinel))

这适用于预期目的:

>>> next(g3)
(0, 1, 2)
>>> next(g3)
(3, 4, 5)
>>> list(g3)
[(6, 7, 8), (9, 10)]

这看起来很笨拙。我试过:

  1. 使用islice,但长度不足似乎难以克服;
  2. iter 中使用哨兵,但 iter 的哨兵版本需要可调用对象,而不是可迭代对象。

是否有更惯用的 Python 3 技术来生成长度为 n 的 block ,包括可能小于 n 的最后一个 chuck ?

我也对生成器函数持开放态度。我正在寻找惯用的东西,而且大多更具可读性。


更新:

DSM 在他删除的答案中的方法我认为非常好:

>>> g3=(iter(lambda it=iter(gen): tuple(islice(it, n)), ()))
>>> next(g3)
(0, 1, 2)
>>> list(g3)
[(3, 4, 5), (6, 7, 8), (9, 10)]

作为一个dup,我对这个问题持开放态度但是链接的问题已经有将近 10 年的历史了,并且集中在一个列表上。 Python 3 中没有 方法生成器,您不知道长度并且一次不想超过一个 block ?

最佳答案

我认为,只要您试图将它装入一个衬里,它就会总是很困惑。 我会硬着头皮在这里使用生成器函数。如果您不知道实际大小(例如,如果 gen 是无限生成器等),则特别有用。

from itertools import islice

def chunk(gen, k):
    """Efficiently split `gen` into chunks of size `k`.

       Args:
           gen: Iterator to chunk.
           k: Number of elements per chunk.

       Yields:
           Chunks as a list.
    """ 
    while True:
        chunk = [*islice(gen, 0, k)]
        if chunk:
            yield chunk
        else:
            break

>>> gen = iter(list(range(11)))
>>> list(chunk(gen))
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]

有人可能有更好的建议,但我会这样做。

关于Python 3 生成器理解生成 block ,包括最后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51446327/

相关文章:

python - 从具有 txt 中指定标签的字典构建数据框

javascript - 通过 yield & co 获得 promise 的值(value)

python - 为什么 join() 不自动将其参数转换为字符串?你什么时候不想让它们成为字符串?

python - 索引错误 : list index out of range python 3. 4

python - 如何连接以下两个矩阵?

python-3.x - Matplotlib 相关热图中缺少标签

c - 为什么我仍然收到这些错误?

python - 解决生成器中的评估时间差异

python - 如何检查具有列表或字典的元组是否为空

python - 如何使用 Python Pandas 读取对象列的属性