【发布时间】:2017-09-03 03:29:25
【问题描述】:
我似乎认为,尽管网上有很多算法和函数可以从唯一项目列表中生成任意大小的唯一组合,但在非唯一项目列表的情况下(即包含相同值重复的列表。)
问题是如何在生成器函数中生成 ON-THE-FLY all 非唯一列表中的唯一组合没有 过滤掉重复项的计算成本很高?
现在,由于对这个问题有一个赏金动机的答案,因此更容易更清楚地说明我期望实现的目标:
首先让我们提供代码说明如何检查组合 comboB 是否被认为与另一个组合 (comboA) 重复:
comboA = [1,2,2]
comboB = [2,1,2]
print("B is a duplicate of A:", comboA.sort()==comboB.sort())
在给定的示例中,B 是 A 的副本,并且 print() 打印 True。
在非唯一列表的情况下获得能够即时提供唯一组合的生成器函数的问题在这里解决:Getting unique combinations from a non-unique list of items, FASTER?,但提供的生成器函数需要查找并需要内存,这会导致问题以防万一的大量组合。
在当前版本的答案提供函数中,无需任何查找即可完成这项工作,并且在这里似乎是正确的答案,但是...
摆脱查找的目的是在列表重复的情况下加快生成唯一组合的速度。
我最初(编写此问题的第一个版本)错误地认为不需要创建用于确保唯一性的查找集的代码有望比需要查找的代码具有优势。 事实并非如此。至少并非总是如此。到目前为止提供的答案中的代码不使用查找,但在没有冗余列表或列表中只有几个冗余项目的情况下生成所有组合需要更多时间。
这里有一些时间来说明当前的情况:
-----------------
k: 6 len(ls): 48
Combos Used Code Time
---------------------------------------------------------
12271512 len(list(combinations(ls,k))) : 2.036 seconds
12271512 len(list(subbags(ls,k))) : 50.540 seconds
12271512 len(list(uniqueCombinations(ls,k))) : 8.174 seconds
12271512 len(set(combinations(sorted(ls),k))): 7.233 seconds
---------------------------------------------------------
12271512 len(list(combinations(ls,k))) : 2.030 seconds
1 len(list(subbags(ls,k))) : 0.001 seconds
1 len(list(uniqueCombinations(ls,k))) : 3.619 seconds
1 len(set(combinations(sorted(ls),k))): 2.592 seconds
以上时间说明了两个极端:没有重复,只有重复。所有其他时间都在这两者之间。
我对上述结果的解释是纯 Python 函数(没有 itertools 或其他 C 编译模块)可以非常快,但也可以慢得多,具体取决于列表中有多少重复项。因此,可能无法为提供所需功能的 Python .so 扩展模块编写 C++ 代码。
【问题讨论】:
-
如何确定 (1,2,2) 和 (2,1,2) 中的哪一个是“正确的”?
-
你的第一条评论就是我要找的。span>
-
@Claudio 我还发现了this thread,其中包含更更简单的iterative algorithm(需要对输入进行排序)和recursive algorithm的代码。它们似乎比当前的答案更有效率,但我还没有真正测试过它们。
-
@lazydog 请参阅此处cython.org 和此处stackoverflow.com/questions/43729052/…,如果您希望使用现成的模块比当前最佳答案更快,请随时提供另一个答案。您的答案中的递归算法已经提供了一个非常好的 C 编译 Python 模块,它仅比使用带有循环而不是递归的算法的迭代器类版本的 Cython 优化代码慢一点。抱歉 - 还没有时间将问题更新为有关此主题的最新技术。
标签: c++ python-3.x unique combinations lookup