2番目が短い圧縮されたPythonジェネレーター:暗黙的に消費される要素を取得する方法 質問する

2番目が短い圧縮されたPythonジェネレーター:暗黙的に消費される要素を取得する方法 質問する

次のように、長さが異なる可能性のある 2 つのジェネレータを解析しますzip

for el1, el2 in zip(gen1, gen2):
    print(el1, el2)

ただし、gen2の要素が少ない場合は、 の余分な要素が 1 つgen1「消費」されます。

例えば、

def my_gen(n:int):
    for i in range(n):
        yield i

gen1 = my_gen(10)
gen2 = my_gen(8)

list(zip(gen1, gen2))  # Last tuple is (7, 7)
print(next(gen1))  # printed value is "9" => 8 is missing

gen1 = my_gen(8)
gen2 = my_gen(10)

list(zip(gen1, gen2))  # Last tuple is (7, 7)
print(next(gen2))  # printed value is "8" => OK

どうやら、値が欠落しています (8前の例の場合)。これは、に要素がもうないことに気づく前にgen1が読み取られる (したがって値 が生成される) ためです。ただし、この値はユニバース内で消えます。が「長い」場合、このような「問題」は発生しません。8gen2gen2

質問: この欠落値を取得する方法はありますか (つまり、8前の例のように)? ... 理想的には、可変数の引数を使用します (zipのように)。

注記:私は現在、を使用して別の方法で実装していますitertools.zip_longestが、または同等のものを使用してこの欠落値を取得する方法が本当に知りたいですzip

注2:新しい実装を提出して試してみたい場合に備えて、この REPL でさまざまな実装のテストをいくつか作成しました :)https://repl.it/@jfthuong/MadPhysicistChester

ベストアンサー1

箱から出してすぐにジップ()一致しないアイテムを破棄するようにハードワイヤードされているので、値を記憶する方法が必要です前に彼らは消費されてしまいます。

itertoolと呼ばれるティー()はこの目的のために設計されました。これを使用して、最初の入力イテレータの「シャドウ」を作成できます。2 番目のイテレータが終了したら、シャドウ イテレータから最初のイテレータの値を取得できます。

既存のツールを使用し、C 速度で実行し、メモリ効率の高い方法の 1 つを次に示します。

>>> from itertools import tee
>>> from operator import itemgetter

>>> iterable1, iterable2 = 'abcde', 'xyz' 

>>> it1, shadow1 = tee(iterable1)
>>> it2 = iter(iterable2)
>>> combined = map(itemgetter(0, 1), zip(it1, it2, shadow1))
 
>>> list(combined)
[('a', 'x'), ('b', 'y'), ('c', 'z')]
>>> next(shadow1)
'd'

おすすめ記事