You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

元组列表的类排列组合生成问题:去重且保留重复元组组合

解决多重组合生成问题

嗨,我明白你要的是那种允许重复选同一个元组、但不考虑顺序的“组合”——其实这在数学里叫多重组合,正好Python的itertools库有现成的工具能搞定,比你原来的方法高效多了!

先说说你原来代码的问题:

  • 用itertools.product生成的是所有带顺序的笛卡尔积,比如你提到的[(1,20), (1,20), (1,21)]、[(1,20), (1,21), (1,20)]这些不同顺序的都会被生成,转成集合虽然能去重,但当你的元组列表变大、选取数量增多时,这种方法会生成大量冗余数据,效率很低。
  • 另外你说set会丢失全重复的结果?其实不会,((1,20), (1,20), (1,20))是可哈希的元组,会被正常保留在集合里,可能是你测试时的小疏漏~不过不管怎样,这个思路不是最优解。

正确解法:用itertools.combinations_with_replacement

这个函数就是专门为你的需求设计的:从给定序列中选取指定数量的元素,允许重复选取同一个元素,且不生成顺序不同的重复项。直接一步到位,不需要额外去重操作。

举个例子,针对你的输入:

import itertools

list_of_tuples = [(1,20), (1,21), (2,18), (2,19)]
# 生成选取3个元素的多重组合
results = list(itertools.combinations_with_replacement(list_of_tuples, 3))

生成的结果会包含:

  • 像((1,20), (1,20), (1,20))这样的全重复元组组合
  • 对于包含不同元组的组合,比如(1,20)和(1,21)的组合,只会保留((1,20), (1,20), (1,21))这一种(按原列表的元素顺序排列),不会出现其他顺序的版本,完全符合你“顺序不同算同一个,只保留一个”的要求。

为什么这个方法更好?

combinations_with_replacement直接生成符合要求的结果,不需要先生成所有排列再去重。比如你的例子里,它只会生成20个结果(数学上的组合数C(4+3-1,3)=20),而product会生成64个结果,再转set虽然也能得到20个,但前者的效率要高得多,尤其是当选取数量k很大的时候,差距会非常明显。

内容的提问来源于stack exchange,提问作者nirnroot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:05:28