如何从扁平列表生成所有无重复顺序的列表与子列表组合?
生成列表的所有不重复集合划分
看起来你要解决的是集合划分问题——把原列表的所有元素分成若干非空子集,且不考虑子集的顺序(避免像[["aaa"], ["bbb"], ["ccc"]]和[["bbb"], ["aaa"], ["ccc"]]这类重复),同时每个划分必须包含所有元素。
递归实现方案
这个需求用递归的方式最直观,而且能自然避免重复。核心思路是:从第一个元素开始,要么把它单独作为一个子集,要么把它合并到后续元素的任意子集中,递归处理剩下的元素。
def set_partitions(lst): if not lst: yield [] return # 取列表第一个元素 first = lst[0] # 递归处理剩下的元素,得到所有可能的划分 for rest_partition in set_partitions(lst[1:]): # 情况1:第一个元素单独作为一个子集 yield [[first]] + rest_partition # 情况2:把第一个元素依次加入到剩余划分的每个子集中 for i in range(len(rest_partition)): updated_subset = [first] + rest_partition[i] yield rest_partition[:i] + [updated_subset] + rest_partition[i+1:]
测试一下
用你的示例列表测试:
l = ["aaa", "bbb", "ccc"] for partition in set_partitions(l): print(partition)
输出正好符合你的要求:
[['aaa'], ['bbb'], ['ccc']] [['aaa', 'bbb'], ['ccc']] [['aaa', 'ccc'], ['bbb']] [['bbb', 'ccc'], ['aaa']] [['aaa', 'bbb', 'ccc']]
为什么不会产生重复?
这个方法通过固定子集的相对顺序避免了重复:我们总是把原列表中靠前的元素优先放在划分的前面,或者合并到后续的子集中,不会出现子集顺序颠倒的情况(比如不会生成[["bbb"], ["aaa"], ["ccc"]])。
关于itertools.combinations
itertools.combinations主要用于生成元素的组合,直接用它来生成划分会比较绕——你需要先确定分组的大小,再生成对应的组合,还要处理分组的不重复问题,不如递归方案简洁直观。
内容的提问来源于stack exchange,提问作者Thomas Karaouzene
相关产品推荐
相关产品推荐

