(潜在的に)異なる長さの2つのジェネレータをZip
で解析したい:
for el1, el2 in Zip(gen1, gen2):
print(el1, el2)
ただし、gen2
の要素が少ない場合、gen1
の1つの追加要素が「消費」されます。
例えば、
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
に要素がないことを認識する前に8
が読み取られる(つまり、値gen2
が生成される)ためです。しかし、この値は宇宙で消えます。 gen2
が「長い」場合、そのような「問題」はありません。
[〜#〜] question [〜#〜]:この欠損値を取得する方法はありますか(つまり、前の例では8
) )? ...理想的には、可変数の引数を使用します(Zip
のように)。
[〜#〜]ノート[〜#〜]:I現在、itertools.Zip_longest
を使用して別の方法で実装していますが、Zip
または同等のものを使用して、この欠落している値を取得する方法を本当に思います。
注2:私はさまざまな実装のいくつかのテストを作成しましたthis REPL送信して新しい実装を試したい場合:) https://repl.it/@jfthuong/MadPhysicistChester
コードを再利用する場合、最も簡単な解決策は次のとおりです。
from more_itertools import peekable
a = peekable(a)
b = peekable(b)
while True:
try:
a.peek()
b.peek()
except StopIteration:
break
x = next(a)
y = next(b)
print(x, y)
print(list(a), list(b)) # Misses nothing.
このコードは、セットアップを使用してテストできます。
def my_gen(n: int):
yield from range(n)
a = my_gen(10)
b = my_gen(8)
印刷されます:
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
[8, 9] []
基本的なforループでドロップされた値を取得できないと思います。使い果たされたイテレータはZip(..., ...).__iter__
から取得され、一度使い果たされてアクセスできなくなるためです。
Zipを変更すると、ドロップしたアイテムの位置をハックコードで取得できます)
z = Zip(range(10), range(8))
for _ in iter(z.__next__, None):
...
_, (one, other) = z.__reduce__()
_, (i_one,), p_one = one.__reduce__() # p_one == current pos, 1 based
import itertools
val = next(itertools.islice(iter(i_one), p_one - 1, p_one))