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番目のグループのみを取得したい場合、どうすればよいですか?
最初のアプローチが機能しない理由は、リストを作成するとグループが「消費」されるためです
_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
呼び出しが親に対して反復されたためになくなりました。
単純なジェネレータ式など、イテレータを2回繰り返してみても何も変わりません。
_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
_