itertools モジュール(2)

昨日の続き。

一番短い入力シーケンスで止まるイテレータ

itertools.chain は引数をひとつのシーケンスのようにつなげてくれる。

>>> for x in itertools.chain('abc', 'def', 'ghi'):
...     print x
...
a
b
c
d
e
f
g
h
i

itertools.compress は2つのシーケンスを引数にとり、2つ目のシーケンスの要素が真の場合、対応する1つ目のシーケンスの要素を返す。

>>> for x in itertools.compress('abcdef', [0,1,0,1,1,0]):
...     print x
...
b
d
e

itertools.dropwhile は Haskell の dropWhile と同じように先頭の条件が真になる要素を取り除いた残りの要素を返す。

>>> for x in itertools.dropwhile(lambda x: x < 5, [1,3,4,5,7,8,5,3]):
...     print x
...
5
7
8
5
3

itertools.groupby は少しわかりにくい。このイテレータが返すのは、第2引数で指定した関数の返り値と、その返り値で分けられたグループ(itertools._grouperオブジェクト)だ。

>>> for k, g in itertools.groupby([2,4,6,8,10,1,3,5,7,9], lambda x: x % 2):
...     print k
...     print g
...
0
<itertools._grouper object at 0x02127FD0>
1
<itertools._grouper object at 0x02127EB0>

このグループ自体がイテレータになっていて、繰り返し処理をすることができる。

>>> for k, g in itertools.groupby([2,4,6,8,10,1,3,5,7,9], lambda x: x % 2):
...     print 'key: ', k
...     for x in g:
...         print x
...
key:  0
2
4
6
8
10
key:  1
1
3
5
7
9

ちなみに、あらかじめ関数の値でソートされているのが前提のようで、ばらばらなものをまとめてくれたりはしない。

>>> for k, g in itertools.groupby(range(10), lambda x: x % 2):
...     print 'key: ', k
...     for x in g:
...         print x
...
key:  0
0
key:  1
1
key:  0
2
key:  1
3
key:  0
4
key:  1
5
key:  0
6
key:  1
7
key:  0
8
key:  1
9

itertools.ifilter は filter関数と同じ。何が違うんだろ。

>>> for i in itertools.ifilter(lambda x: x%2, range(10)):
...     print i
...
1
3
5
7
9

itertools.ifilter と逆の動作をするのが itertools.ifilterfalse。条件が偽になる要素を返す。

>>> for i in itertools.ifilterfalse(lambda x: x%2, range(10)):
...     print i
...
0
2
4
6
8

itertools.islice はリストのスライスと同じようだ。これもちょっとどう違うのかわからない。
引数は、seq、start、stop、step の順。startとstepは省略できる。

>>> for c in itertools.islice('abcdefghi', 2, 6, 2):
...     print c
...
c
e

今日はここまで。時間があれば続きを書くかも。