如何改变一个itertools"石斑鱼"将对象放入列表中

时间:2017-06-12 01:01:26

标签: python itertools

我正在尝试学习如何在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组,我该怎么做?

1 个答案:

答案 0 :(得分:12)

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

创建该列表时,这些组会被“消耗”
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']
[]

BTW,如果你实际上不需要它的内容,这是获得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