在 Python 3 中,zip(*iterables)
自 documentation
返回一个元组迭代器,其中第 i 个元组包含来自每个参数序列或可迭代对象的第 i 个元素。当最短的输入迭代用完时,迭代器停止。
举个例子,我正在跑步
for x in zip(a,b):
f(x)
有没有办法找出哪些可迭代对象 a
或 b
导致 zip 迭代器停止?
假设 len()
不可靠并且迭代 a
和 b
以检查它们的长度是不可行的。
答案 0 :(得分:0)
我认为简给出了最好的答案。基本上,您希望单独处理 zip 中的最后一次迭代。
import itertools as it
a = (x for x in range(5))
b = (x for x in range(3))
iterables = ((it.chain(g,[f"generator {i} was exhausted"]) for i,g in enumerate([a,b])))
for i, j in zip(*iterables):
print(i, j)
# 0 0
# 1 1
# 2 2
# 3 generator 1 was exhausted
答案 1 :(得分:0)
如果你只有两个可迭代对象,你可以使用下面的代码。 The exhausted[0]
将拥有迭代器耗尽的指标。 None 的值表示两者都已耗尽。
但是我必须说我不同意 len()
不可靠。事实上,您应该依靠 len()
调用来确定答案。 (除非你告诉我们你不能的原因。)
def f(val):
print(val)
def manual_iter(a,b, exhausted):
iters = [iter(it) for it in [a,b]]
iter_map = {}
iter_map[iters[0]] = 'first'
iter_map[iters[1]] = 'second'
while 1:
values = []
for i, it in enumerate(iters):
try:
value = next(it)
except StopIteration:
if i == 0:
try:
next(iters[1])
except StopIteration:
return None
exhausted.append(iter_map[it])
return iter_map[it]
values.append(value)
yield tuple(values)
if __name__ == '__main__':
exhausted = []
a = [1,2,3]
b = [10,20,30]
for x in manual_iter(a,b, exhausted):
f(x)
print(exhausted)
exhausted = []
a = [1,2,3,4]
b = [10,20,30]
for x in manual_iter(a,b, exhausted):
f(x)
print(exhausted)
exhausted = []
a = [1,2,3]
b = [10,20,30,40]
for x in manual_iter(a,b, exhausted):
f(x)
print(exhausted)
答案 2 :(得分:0)
我找到了以下解决方案,该解决方案将 zip
替换为 for
循环,仅覆盖第一个可迭代对象,并在循环内迭代第二个。
ib = iter(b)
for r in a:
try:
s = next(ib)
except StopIteration:
print('Only b exhausted.')
break
print((r,s))
else:
try:
s = next(ib)
print('Only a exhausted.')
except StopIteration:
print('a and b exhausted.')
这里 ib = iter(b)
确保它在 b
是序列或生成器对象时也能工作。 print((r,s))
将替换为问题中的 f(x)
。