获取任意长度的所有组合而无子组合

时间:2019-01-10 18:36:16

标签: python combinations itertools

我有一个元组(项目,值)列表,我想将其所有可能的组合取到最大总值,除了已经找到的那些组合的“子组合”。假设我有清单:

items = [("a", 1), ("b", 3), ("b", 3), ("c", 10), ("d", 15)]
combinations = [combo for i in range(len(items), 0, -1) for combo in list(itertools.combinations(items, i)) if sum([item[1] for item in combo]) < 16]

结果是:

[(('a', 1), ('b', 3), ('b', 3)), (('a', 1), ('b', 3), ('c', 10)), (('a', 1), ('b', 3), ('c', 10)), (('a', 1), ('b', 3)), (('a', 1), ('b', 3)), (('a', 1), ('c', 10)), (('a', 1), ('d', 15)), (('b', 3), ('b', 3)), (('b', 3), ('c', 10)), (('b', 3), ('c', 10)), (('a', 1),), (('b', 3),), (('b', 3),), (('c', 10),), (('d', 15),)]

但是我想得到:

[(('a', 1), ('b', 3), ('b', 3)), (('a', 1), ('b', 3), ('c', 10)), (('d', 15))]

是否可以消除“子组合”,而要经过很长的if(实际列表要大得多)吗?

1 个答案:

答案 0 :(得分:0)

好的,应该可以。

from itertools import combinations

items = [("a", 1), ("b", 3), ("b", 3), ("c", 10), ("d", 15)]

res = []
for l in range(len(items), 0, -1):
    cb = combinations(items, l)
    cbl = [i for i in cb if sum([j[1] for j in i]) < 16]
    for cc in cbl:
        if not any([set(cc).issubset(el) for el in res]):
            res.append(cc)

print(res)

此打印:

[(('a', 1), ('b', 3), ('b', 3)), (('a', 1), ('b', 3), ('c', 10)), (('d', 15),)]

请注意,如果您有很多物品,此代码可能会很慢,因为它会重复多次以检查给定的组合是否不是任何已被接受的组合的子集。也许有更有效的解决方案。