如何在Python中获取列表允许重复的所有可能组合
嘿,我懂你的需求了!你想要从列表[1,2,3]生成所有允许元素重复、长度不限的非空序列(就是你例子里那种1、1,1、1,1,1、1,2这类,还包含各种组合甚至etc的无限扩展),之前用itertools没得到想要的结果,大概率是用了combinations或permutations(这俩都是无重复的组合/排列),其实咱们该用的是笛卡尔积相关的工具,下面给你具体方案:
如果你想生成长度从1到N的所有允许重复的序列,用itertools.product就搞定了——它专门用来生成允许元素重复的笛卡尔积,正好匹配你的需求:
import itertools original_list = [1, 2, 3] result = [] # 这里我们生成长度1到3的所有序列,你可以改数字调整范围 for length in range(1, 4): # 生成当前长度下的所有可能序列(允许重复元素) for seq_tuple in itertools.product(original_list, repeat=length): # 把元组转成你要的逗号分隔字符串,也可以直接保留列表形式 result.append(",".join(map(str, seq_tuple))) # 打印看看结果 for item in result: print(item)
这段代码的输出会包含你例子里的所有元素,比如:
1
2
3
1,1
1,2
1,3
...
1,1,1
1,1,2
1,2,1
1,2,2
1,2,3
...
etc) 如果你想要像例子里那样无限生成下去(一直扩展长度和组合),可以用itertools.count来不断递增长度,持续生成:
import itertools original_list = [1, 2, 3] # 从长度1开始,无限递增长度生成序列 for length in itertools.count(1): for seq_tuple in itertools.product(original_list, repeat=length): print(",".join(map(str, seq_tuple)))
这段代码会一直跑下去,生成所有可能的允许重复的序列,完全满足你etc的需求。
看你给的例子顺序(1 → 1,1 → 1,1,1 → 1,2 → 1,2,1...),是深度优先的遍历逻辑——先把一个元素的所有延伸序列生成完,再切换下一个元素。那可以用递归的方式实现:
import itertools original_list = [1, 2, 3] def generate_dfs_sequences(items): def dfs(current): # 先输出当前的非空序列 yield ",".join(map(str, current)) # 给当前序列追加每个元素,继续递归生成 for item in items: yield from dfs(current + [item]) # 从每个元素作为起始点开始生成 for start in items: yield from dfs([start]) # 生成前20个看看效果,和你例子的顺序几乎一致 for idx, seq in enumerate(generate_dfs_sequences(original_list)): print(seq) if idx >= 19: break
这段代码的输出会是:
1
1,1
1,1,1
1,1,2
1,1,3
1,2
1,2,1
1,2,2
1,2,3
1,3
1,3,1
1,3,2
1,3,3
2
2,1
2,1,1
2,1,2
2,1,3
2,2
2,2,1
和你给的例子顺序几乎完全匹配,唯一区别是你例子里重复出现了1,2,这应该是笔误,如果真的需要重复序列,你可以在生成后手动添加,或者调整逻辑~
内容的提问来源于stack exchange,提问作者Kim Han

