为什么`zip`似乎消耗了`groupby`迭代?

ACh*_*ion 4 python python-itertools python-3.x

因此,使用分割列表itertools.groupby()相当容易.

>>> import itertools as it
>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4, 2], lambda p: p==2)
>>> for x, y in iterable:
...     print(x, list(y))
...     next(iterable)
False [1]
False [3, 4, 5]
False [3, 4]
Run Code Online (Sandbox Code Playgroud)

按预期工作.但是使用常见的python习惯用法zip多次迭代迭代器,一次只能逐步完成2,这似乎打破了局面.

>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4, 2], lambda p: p==2)
>>> for (x, y), _ in zip(iterable, iterable):
...     print(x, list(y))
False []
False []
False []
Run Code Online (Sandbox Code Playgroud)

添加一个print(y)显示预期的嵌套迭代<itertools._grouper object at 0xXXXXXXXX>,但我显然遗漏了grouper对象为什么为空的东西.任何人都能解释一下吗?

如果我有一个不均匀的列表并使用我得到一个更奇怪的结果itertools.zip_longest:

>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4], lambda p: p==2)
>>> for (x, y), _ in it.zip_longest(iterable, iterable, fillvalue=None):
...     print(x, list(y))
False []
False []
False [4]
Run Code Online (Sandbox Code Playgroud)

更新:简单修复是使用itertools.islice():

>>> iterable = it.groupby([1, 2, 3, 4, 5, 2, 3, 4, 2], lambda p: p==2)
>>> for x, y in it.islice(iterable, None, None, 2):
...     print(x, list(y))
False [1]
False [3, 4, 5]
False [3, 4]
Run Code Online (Sandbox Code Playgroud)

use*_*ica 6

groupby文件警告您,

返回的组本身是一个迭代器,它使用groupby()共享底层的iterable.由于源是共享的,因此当groupby()对象处于高级时,前一个组将不再可见.

当您zip生成一((key, group), (key, group))对时,它会使groupby迭代器超过第一个组,从而使第一个组无法使用.您需要在推进之前实现该组:

iterable = ((key, list(group)) for (key, group) in it.groupby([1, 2, 3, 4, 5, 2, 3, 4, 2], lambda p: p==2))
for (x, y), _ in zip(iterable, iterable):
    print(x, y)
Run Code Online (Sandbox Code Playgroud)