`list(itertools.groupby)`的反直觉行为

3

让我来演示一下。它已经咬了我两次,第一次我放弃了,认为我无法理解groupby的工作原理。我正在使用`Python3.6'。

我有一个以x.y格式表示的元素列表,我想按y进行分组。

a = ['1D.5', '2D.5', '3D.5', '1D.10', '2D.10', '3D.10', '1D.20', '2D.20', '3D.20', '1D.100', '2D.100', '3D.100']
groups = list(itertools.groupby(a, key=lambda x: x.split('.')[-1]))
for gname, glist in groups:
    print(list(glist))

这会导致以下结果。
[]
[]
[]
['3D.100']

奇怪!

然而这很有效。

groups = itertools.groupby(a, key=lambda x: x.split('.')[-1])
for gname, glist in groups:
    print(list(glist))

['1D.5', '2D.5', '3D.5']
['1D.10', '2D.10', '3D.10']
['1D.20', '2D.20', '3D.20']
['1D.100', '2D.100', '3D.100']

这次我没有在 itertools.groupby 上调用 list。这种行为背后肯定有一些技术原因,但是根据我的经验,这非常反直觉,可能是错误的!为什么在迭代器上调用 list 会使其内容无效? PS:groupby 的文档在其实现细节中有以下两行。
# [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D

我猜测list(some generator)不能保证给出与“相同”的列表推导式相同的结果,这种情况是否正确?
1个回答

2
< p > groupby 的分组迭代器依赖于先前的迭代器。因此,将这些分组迭代器转换为列表的正确方法是确保在生成每个迭代器时都进行复制。

list((g, list(it)) for g, it in itertools.groupby(a, key=func))

仅靠外部的list无法复制内部迭代器it,它们只能被顺序访问一次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接