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

时间:2018-05-05 08:57:27

标签: python group-by itertools

让我来证明一下。它咬了我两次,第一次我放弃了以为我无法理解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']

不同之处在于,这次我没有在list上致电itertools.groupby。肯定有这种行为背后有一些技术原因,但根据我对python生成器的经验,这是非常违反直觉的,可能是错误的!

为什么在迭代器上调用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 个答案:

答案 0 :(得分:2)

groupby的组迭代器依赖于先前的迭代器。因此,从这些组迭代器中生成列表的正确方法是确保在生成每个迭代器时复制每个列表。

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

单独的外部list不会复制只能按顺序访问一次的内部迭代器it