使用itertools.product时如何跳过部分迭代,实现类似嵌套循环的break效果
问题描述
现有三个已排序的升序列表:A = [1, 2, 3, 4]B = [3, 4, 5]C = [2, 3, 4]
需求是找到所有三数之和小于10的组合。原三层嵌套循环实现可以利用列表有序的特性,在三数之和不满足条件时直接break提升运行效率,现在改用itertools.product生成所有组合,需要实现类似的跳过迭代效果。
实现方案
itertools.product生成笛卡尔积的顺序为固定前两个元素,先遍历完第三个列表的所有元素,再更新第二个元素,第二个列表遍历完成后再更新第一个元素,刚好和三层嵌套循环的遍历顺序一致,我们可以将其转为手动控制的迭代器,匹配原逻辑实现无效组合跳过:
完整代码(效率和原三层循环一致)
import itertools A = [1, 2, 3, 4] B = [3, 4, 5] C = [2, 3, 4] threshold = 10 # 转换为手动控制的迭代器 prod_iter = iter(itertools.product(A, B, C)) while True: try: a, b, c = next(prod_iter) except StopIteration: # 遍历完成直接退出 break current_sum = a + b + c if current_sum < threshold: print(a, b, c) else: # 1. 列表C为升序,当前a、b下剩余的c都更大,全部跳过 remain_c_num = len(C) - C.index(c) - 1 for _ in range(remain_c_num): next(prod_iter, None) # 2. 如果当前是C的第一个元素就不满足,说明当前b下所有c都不满足,跳过当前a下剩余的所有b对应的组合 if c == C[0]: remain_b_num = len(B) - B.index(b) - 1 skip_total = remain_b_num * len(C) for _ in range(skip_total): next(prod_iter, None) # 3. 如果当前是B的第一个元素就不满足,说明所有更大的b、c都不满足,直接终止整个遍历 if b == B[0]: break
简化版(代码更短,会遍历无效组合,适合数据量小的场景)
如果数据量不大不需要极致性能,可以直接用条件过滤,写法更简洁:
import itertools A = [1, 2, 3, 4] B = [3, 4, 5] C = [2, 3, 4] for a, b, c in itertools.product(A, B, C): if a + b + c >= 10: continue print(a, b, c)
内容的提问来源于stack exchange,提问作者Gilseung Ahn
相关产品推荐
相关产品推荐

