如何将 itertools “grouper”对象变成列表

Posted

技术标签:

【中文标题】如何将 itertools “grouper”对象变成列表【英文标题】:How to turn an itertools "grouper" object into a list 【发布时间】:2017-06-12 01:01:25 【问题描述】:

我正在尝试学习如何在 Python 中使用 itertools.groupby,并且我想找到每组字符的大小。起初我试图看看我是否能找到单个组的长度:

from itertools import groupby
len(list(list( groupby("cccccaaaaatttttsssssss") )[0][1]))

我每次都会得到 0。

我做了一些研究,发现其他人是这样做的:

from itertools import groupby
for key,grouper in groupby("cccccaaaaatttttsssssss"):
    print key,len(list(grouper))

效果很好。我感到困惑的是为什么后面的代码可以工作,而前者却不行?如果我只想得到第 n 组,就像我在原始代码中尝试做的那样,我该怎么做?

【问题讨论】:

顺便说一句,这只是您想法的一种变体,如果您需要通过 Antlr4 通道保存输入的分区(我确实需要这样做),您可以执行类似 groups = itertools.groupby(tokens.tokens, lambda token: token.channel); groups_lists = [(k, list(grouper)) for k, grouper in groups] 的操作。列表推导可能比 Python 循环快一点。 【参考方案1】:

您的第一种方法不起作用的原因是,当您使用

创建该列表时,这些组会被“消耗”
list(groupby("cccccaaaaatttttsssssss"))

引用the groupby docs

返回的组本身就是一个迭代器,它共享底层 可与groupby() 迭代。因为源是共享的,当 groupby()对象是高级的,以前的组不再是 可见。

让我们把它分解成几个阶段。

from itertools import groupby

a = list(groupby("cccccaaaaatttttsssssss"))
print(a)
b = a[0][1]
print(b)
print('So far, so good')
print(list(b))
print('What?!')

输出

[('c', <itertools._grouper object at 0xb715104c>), ('a', <itertools._grouper object at 0xb715108c>), ('t', <itertools._grouper object at 0xb71510cc>), ('s', <itertools._grouper object at 0xb715110c>)]
<itertools._grouper object at 0xb715104c>
So far, so good
[]
What?!

我们的itertools._grouper object at 0xb715104c 是空的,因为它与groupby 返回的“父”迭代器共享其内容,而这些项目现在已经消失,因为第一个list 调用迭代了父级。

如果您尝试对任何迭代器(例如简单的生成器表达式)进行两次迭代,所发生的情况实际上并没有什么不同。

g = (c for c in 'python')
print(list(g))
print(list(g))

输出

['p', 'y', 't', 'h', 'o', 'n']
[]

顺便说一句,如果您实际上不需要它的内容,这是获取 groupby 组长度的另一种方法;它比建立一个列表只是为了找到它的长度要便宜一些(并且使用更少的 RAM)。

from itertools import groupby

for k, g in groupby("cccccaaaaatttttsssssss"):
    print(k, sum(1 for _ in g))

输出

c 5
a 5
t 5
s 7

【讨论】:

这是一个很好的解释。非常感谢!

以上是关于如何将 itertools “grouper”对象变成列表的主要内容,如果未能解决你的问题,请参考以下文章

对象上的 Python itertools 组合

itertools模块

Python标准库13 循环器 (itertools)

使用带有多个键的 Grouper 时填写缺失的日期

python值itertools模块

一日一技:如何让 itertools.tee 线程安全