【Python】SimplePrograms line 15 itertools
プログラム
15行プログラムです。
といっても、そのうちの5行がコメントですが。
from itertools import groupby
lines = '''
This is the
first paragraph.
This is the second.
'''.splitlines()
# Use itertools.groupby and bool to return groups of
# consecutive lines that either have content or don't.
for has_chars, frags in groupby(lines, bool):
if has_chars:
print (' '.join(frags))
# PRINTS:
# This is the first paragraph.
# This is the second.
実行結果
This is the first paragraph.
This is the second.
解説
itertools。
イテレータとは何か。
であるらしい。
Pythonドキュメントには、「itertools」について次のようにあります。
この「itertools」なるものにはいろいろな関数があるようですが、今回はそのうちの「groupby」を使っています。
どうも、よくわからん。
ソフトウェアのドキュメントというのは、何故こうもわかりにくいのだろう。宿命なのか(自戒も含む)。
「iterable」というのは配列のようなものです。「iterable」についてはこちらにも記載しました。
「イテレータ」というのは「iterableなもの」であって「__next__() メソッド」を持ちます。
「iterable」は複数のデータを持ちますが、「連続した同じ値をグルーピングする」というのが「groupby」です。
例えば。
「'AAAABBBCCDAABBB'」のような文字列をグルーピングすると次のようになります。
for k, g in groupby('AAAABBBCCDAABBB'):
k|g
-----|--------------------
A|['A', 'A', 'A', 'A']
B|['B', 'B', 'B']
C|['C', 'C']
D|['D']
A|['A', 'A']
B|['B', 'B', 'B']
あるいは、「[1, 2, 2, 0, 0, 3, 3, 3, 2]」のようなlistをグルーピングするとこんな感じ。
for k, g in groupby([1, 2, 2, 0, 0, 3, 3, 3, 2]):
k|g
-----|--------------------
1|[1]
2|[2, 2]
0|[0, 0]
3|[3, 3, 3]
2|[2]
同じKeyが複数あらわれますが、関数「groupby」は、引数「iterable」がソートされていることを前提としています。
サンプルプログラムは、文字列をKey「bool」でグルーピングしていて、「bool」というのがちょっと意外。
確認してみると、次のようになりました。
for has_chars, frags in groupby(lines, bool):
has_chars|frags
---------|--------------------
False|['']
True|['This is the', 'first paragraph.']
False|['']
True|['This is the second.']
うーん。
まとめていろいろ確認してみた。
line15_list1.py 実行結果
####################
for k, g in groupby('AAAABBBCCDAABBB'):
type k=<class 'str'>
type g:<class 'itertools._grouper'>
k|g
-----|--------------------
A|['A', 'A', 'A', 'A']
B|['B', 'B', 'B']
C|['C', 'C']
D|['D']
A|['A', 'A']
B|['B', 'B', 'B']
####################
for k, g in groupby('AAAABBBCCDAABBB', bool):
type k=<class 'bool'>
type g:<class 'itertools._grouper'>
k|g
-----|--------------------
True|['A', 'A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'D', 'A', 'A', 'B', 'B', 'B']
####################
for k, g in groupby('AAAABBBCCDAABBB', str):
type k=<class 'str'>
type g:<class 'itertools._grouper'>
k|g
-----|--------------------
A|['A', 'A', 'A', 'A']
B|['B', 'B', 'B']
C|['C', 'C']
D|['D']
A|['A', 'A']
B|['B', 'B', 'B']
####################
for k, g in groupby([1, 2, 2, 0, 0, 3, 3, 3, 2], str):
type k=<class 'str'>
type g:<class 'itertools._grouper'>
k|g
-----|--------------------
1|[1]
2|[2, 2]
0|[0, 0]
3|[3, 3, 3]
2|[2]
####################
for k, g in groupby([1, 2, 2, 0, 0, 3, 3, 3, 2], int):
type k=<class 'int'>
type g:<class 'itertools._grouper'>
k|g
-----|--------------------
1|[1]
2|[2, 2]
0|[0, 0]
3|[3, 3, 3]
2|[2]
####################
for k, g in groupby([1, 2, 2, 0, 0, 3, 3, 3, 2], bool):
type k=<class 'bool'>
type g:<class 'itertools._grouper'>
k|g
-----|--------------------
True|[1, 2, 2]
False|[0, 0]
True|[3, 3, 3, 2]
####################
for k, g in groupby([1, 2, 2, 0, 0, 3, 3, 3, 2]):
type k:<class 'int'>
type g:<class 'itertools._grouper'>
k|g
-----|--------------------
1|[1]
2|[2, 2]
0|[0, 0]
3|[3, 3, 3]
2|[2]
ライブラリの動作を隅隅まで見通し難い。
Pythonドキュメントにはレシピもあります。
前記「line15_list1.py」はこちらからダウンロードできます。