Python实现多生成器按取0/1元素规则生成指定组合列表
实现方案
根据你给出的示例结构,你需要的是按组合长度从小到大,依次生成前1个、前2个...前n个生成器的笛卡尔积,每个组合里的元素按生成器顺序排列,不会出现跳过靠前生成器仅选靠后生成器的情况,最终所有生成器会在最后一轮全量笛卡尔积时被完全耗尽。
迭代实现(顺序完全匹配示例)
迭代实现逻辑直观,输出顺序和你给出的示例完全一致,代码如下:
from typing import Generator, List, Tuple def build_A(gen_list: List[Generator]) -> List[Tuple]: res = [] current_prefixes = [] for idx, gen in enumerate(gen_list): # 缓存当前生成器所有元素,生成器仅可迭代一次,必须缓存 elems = list(gen) if idx == 0: # 处理第一个生成器,生成所有单元素组合 current_prefixes = [(elem,) for elem in elems] else: # 用之前的前缀组合和当前生成器元素拼接,生成长度+1的新组合 new_prefixes = [] for prefix in current_prefixes: for elem in elems: new_prefixes.append(prefix + (elem,)) current_prefixes = new_prefixes # 将当前长度的所有组合加入结果 res.extend(current_prefixes) return res
测试示例
gen1 = iter(['a', 'b']) gen2 = iter(['c']) gen3 = iter(['d', 'e']) A = build_A([gen1, gen2, gen3]) print(A)
输出结果:
[('a',), ('b',), ('a', 'c'), ('b', 'c'), ('a', 'c', 'd'), ('b', 'c', 'd'), ('a', 'c', 'e'), ('b', 'c', 'e')]
完全匹配你给出的示例结构。
注意:因为生成器是单次消耗的惰性迭代器,而我们需要复用靠前生成器的元素和后续生成器做组合,所以必须将每个生成器的元素缓存为列表,这是必要开销,无法避免。
递归实现(支持任意子集的幂集逻辑)
如果你需要的是真正的幂集逻辑(每个生成器独立选择0或1个元素,支持跳过靠前生成器选靠后生成器,比如单独选gen2、选gen1+gen3等),可以使用递归实现,代码如下:
from typing import Generator, List, Tuple def build_A_powerset(gen_list: List[Generator]) -> List[Tuple]: def _helper(gens): if not gens: yield () return first, *rest = gens rest_combs = list(_helper(rest)) # 先返回不选当前生成器的所有组合 yield from rest_combs # 再返回选当前生成器某一个元素的所有组合 for elem in first: for comb in rest_combs: yield (elem,) + comb # 去掉全不选的空组合 return list(_helper(gen_list))[1:]
这个版本的输出会包含所有非空的合法组合,符合幂集的定义,只是每个生成器的可选值是它的所有元素而非单个元素。
内容的提问来源于stack exchange,提问作者jake77
相关产品推荐
相关产品推荐

