Python中如何生成列表3个等大小分区的所有组合?
等大小分区所有组合生成方案
直接嵌套调用itertools.combinations选组会引入冗余重复,因为选组的先后顺序会把同一种划分多次生成,先明确需求场景再选对应实现即可,全程只依赖标准库itertools,不需要额外安装第三方包。
场景1:分区带明确标签/顺序
如果三个分区有明确的身份区别(比如对应三个不同的实验组、三个不同的分类),组之间的顺序有实际意义,直接按分层选组合的逻辑实现即可:
- 从全部15个元素中选5个作为第一组
- 从剩余10个元素中选5个作为第二组
- 最后剩下的5个元素自动为第三组
代码实现:
import itertools def ordered_3equal_partitions(vec): group_len = len(vec) // 3 if len(vec) != 3 * group_len: raise ValueError("输入向量长度必须为3的倍数") full_set = set(vec) for g1 in itertools.combinations(full_set, group_len): remain_after_g1 = full_set - set(g1) for g2 in itertools.combinations(remain_after_g1, group_len): g3 = tuple(remain_after_g1 - set(g2)) yield (g1, g2, g3)
- 针对15个元素的输入,该函数总共生成
C(15,5)*C(10,5) = 756756种划分 - 返回结果为生成器,不会一次性占用大量内存,遍历即可拿到所有结果
场景2:分区无顺序区别
如果只是将元素拆分为3个大小相等的集合,组之间没有身份差异,上面的实现会把同一种划分重复计算6次(对应3个组的全排列数)。可以通过锚点法在生成阶段直接去重,不需要先生成全量结果再过滤:固定每一步拆分时的第一个剩余元素必须属于当前选中的组,从根源上消除组顺序带来的重复。
3组场景的简化实现如下:
import itertools def unordered_3equal_partitions(vec): group_len = len(vec) // 3 if len(vec) != 3 * group_len: raise ValueError("输入向量长度必须为3的倍数") vec = list(vec) # 固定第一个元素在第一组,消除三个组的整体排列重复 anchor1 = vec[0] pool = set(vec[1:]) for g1_rest in itertools.combinations(pool, group_len - 1): g1 = (anchor1,) + g1_rest remain_after_g1 = pool - set(g1_rest) # 固定剩余元素的第一个在第二组,消除后两个组的排列重复 anchor2 = next(iter(remain_after_g1)) for g2_rest in itertools.combinations(remain_after_g1 - {anchor2}, group_len - 1): g2 = (anchor2,) + g2_rest g3 = tuple(remain_after_g1 - set(g2)) yield (g1, g2, g3)
- 针对15个元素的输入,该函数总共生成
756756 // 6 = 126126种无重复划分 - 如果输入向量存在重复元素,需要先给每个元素绑定唯一索引再做拆分,否则会生成内容完全一致的重复分区
- 两个实现返回的分组均为元组格式,组内元素顺序不影响划分逻辑
内容的提问来源于stack exchange,提问作者blah_crusader
相关产品推荐
相关产品推荐

