1. ホーム
  2. python

[解決済み] Pythonでリストをペア(current, next)として反復処理する。

2022-04-23 10:06:44

質問

Pythonで、"current"要素と"next"要素を見てリストを反復する必要があることがあります。今までは、以下のようなコードで行っていました。

for current, next in zip(the_list, the_list[1:]):
    # Do something

しかし、同じことをするために、もっと慣用的または効率的な方法はないのでしょうか?

どのように解決するのですか?

の関連例です。 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)

この仕組み

まず、2つの並列イテレータ。 ab が作成されます( tee() の呼び出し)で、どちらも元の反復処理可能な要素の先頭を指しています。2番目のイテレータは b は1つ前に移動します。 next(b, None) )の呼び出し)。このとき a はs0を指しており b は s1 を指す。どちらも ab izip 関数は、2 つのイテレータを受け取り、返された要素のペアを作成し、両方のイテレータを同じ速度で進めることができます。

一つ注意点があります。 tee() 関数は、互いに独立して進むことのできる2つのイテレータを生成しますが、それには代償が伴います。もし片方のイテレータがもう片方よりも先に進んでしまったら、その時点で tee() は、2 番目のイテレータが消費するまでの間、消費した要素をメモリ内に保持する必要があります (元のイテレータを「巻き戻す」ことはできません)。ここでは、一方のイテレータが他方より1歩進んでいるだけなので問題ありませんが、一般に、この方法では大量のメモリを使用しがちです。

また tee() を取ることができます。 n パラメータを使用すると、2つ以上の並列イテレータに使用することもできます。

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)