以下はitertoolsモジュールのドキュメントからの関連する例です:
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
Python 2の場合は、次のitertools.izip
代わりに必要ですzip
。
import itertools
def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = itertools.tee(iterable)
next(b, None)
return itertools.izip(a, b)
仕組み:
まず、二つの平行なイテレータ、a
およびb
作成される(tee()
コール)、オリジナルイテラブルの最初の要素の両方指します。2番目のイテレーターb
は1ステップ先に移動します(next(b, None)
)呼び出し)。この時点でa
、s0をb
指し、s1 を指します。双方a
とb
独立オリジナルイテレータを横切ることができる- izip関数は、2回の反復子をとり、同じペースで、両方のイテレータを前進、返された要素のペアを作ります。
注意点:このtee()
関数は、互いに独立して進行できる2つの反復子を生成しますが、コストがかかります。イテレータの1つが他のイテレータより先に進む場合tee()
、2番目のイテレータもそれらを消費するまで、消費された要素をメモリに保持する必要があります(元のイテレータを「巻き戻す」ことはできません)。ここでは、1つのイテレータが他のイテレータよりも1ステップだけ進んでいるため問題ではありませんが、一般に、この方法で多くのメモリを使用するのは簡単です。
パラメータtee()
をとることができるのでn
、これは3つ以上の並列イテレータにも使用できます。
def threes(iterator):
"s -> (s0,s1,s2), (s1,s2,s3), (s2, s3,4), ..."
a, b, c = itertools.tee(iterator, 3)
next(b, None)
next(c, None)
next(c, None)
return zip(a, b, c)