我有重复元素的列表,例如array = [2,2,2,7]
。
如果我使用建议的in this answer解决方案(使用itertools.combinations()
),我会得到:
()
(7,)
(2,)
(2,)
(2,)
(7, 2)
(7, 2)
(7, 2)
(2, 2)
(2, 2)
(2, 2)
(7, 2, 2)
(7, 2, 2)
(7, 2, 2)
(2, 2, 2)
(7, 2, 2, 2)
正如您可以看到一些'组合'重复,例如(7,2,2)
出现了3次。
我想要的输出是:
()
(7,)
(2,)
(7, 2)
(2, 2)
(7, 2, 2)
(2, 2, 2)
(7, 2, 2, 2)
我可以检查重复组合的输出,但我不觉得这是解决这个问题的最佳方法。
答案 0 :(得分:4)
您可以获取组合的集合,然后将它们链接在一起。
from itertools import chain, combinations
arr = [2, 2, 2, 7]
list(chain.from_iterable(set(combinations(arr, i)) for i in range(len(arr) + 1)))
# [(), (7,), (2,), (2, 7), (2, 2), (2, 2, 2), (2, 2, 7), (2, 2, 2, 7)]
答案 1 :(得分:2)
您需要维护一组以相同方式排序的元组:
import itertools as it
desired=set([(),(7,),(2,),(7, 2),(2, 2),(7, 2, 2),(2, 2, 2),(7, 2, 2, 2)])
result=set()
for i in range(len(array)+1):
for combo in it.combinations(array, i):
result.add(tuple(sorted(combo, reverse=True)))
>>> result==desired
True
答案 2 :(得分:1)
不使用itertools.combinations()
和set
:
from collections import Counter
import itertools
def powerset(bag):
for v in itertools.product(*(range(r + 1) for r in bag.values())):
yield Counter(zip(bag.keys(), v))
array = [2, 2, 2, 7]
for s in powerset(Counter(array)):
# Convert `Counter` object back to a list
s = list(itertools.chain.from_iterable(itertools.repeat(*mv) for mv in s))
print(s)
我认为您的问题可以替代地说是找到多重集的权力集,至少根据this definition。
但值得注意的是,上面显示的方法会慢于其他答案中的解决方案,例如this one只会将itertools.combinations()
的结果分组到set
以删除重复项,尽管看起来效率较低,但实际上它仍然更快,因为在Python中迭代比在C中慢得多(参见itertoolsmodule.c实现itertools.combinations()
)。
通过我的有限测试,当你的数组中有大约14个不同的元素时,这个答案中显示的方法将优于前面提到的方法,每个元素的平均多重性为2(此时另一种方法开始消失,运行速度慢很多倍,但是在这种情况下,任何一种方法的运行时间都不超过30秒,因此如果考虑性能,那么您可能需要考虑在C中实现应用程序的这一部分。