Search code examples
pythonpython-2.7setpowerset

return combinations having all element present


I have a list say lis1 = [1,2,3] and a list of subset of above list say

lis2 = [[1,2],[2,3],[3],[1],[2]]

I want to generate all combinations of lis2 such that all items of lis1 should present in the combination.

For eg. this is a valid combinations

one such combination is [[1,2],[2,3]] (all items of lis1 i.e [1,2,3] is present in it)

whereas this is not

[[1,2],[1],[2]] # (3 is not present in it)

What I did was generated powerset of lis2 via this function

from itertools import chain, combinations

def powerset(iterable):
    s = list(iterable)
    return chain.from_iterable(combinations(s, r) for r in range(1,len(s)+1))

But as obvious the returning set contain combinations which are of type

[[1,2],[1],[2]] # (3 is not present in it)

How do I check for the combinations which contain all the item of lis1


Solution

  • You can apply your powerset function to get combinations of subsets and filter the results:

    >>> lis1 = [1,2,3]
    >>> lis2 = [[1,2],[2,3],[3],[1],[2]]
    >>> filter(lambda s: set(sum(s,[])) == set(lis1), powerset(lis2))
    [([1, 2], [2, 3]),
     ([1, 2], [3]),
     ([2, 3], [1]),
     ([1, 2], [2, 3], [3]),
     ([1, 2], [2, 3], [1]),
     ([1, 2], [2, 3], [2]),
     ([1, 2], [3], [1]),
     ([1, 2], [3], [2]),
     ([2, 3], [3], [1]),
     ([2, 3], [1], [2]),
     ([3], [1], [2]),
     ([1, 2], [2, 3], [3], [1]),
     ([1, 2], [2, 3], [3], [2]),
     ([1, 2], [2, 3], [1], [2]),
     ([1, 2], [3], [1], [2]),
     ([2, 3], [3], [1], [2]),
     ([1, 2], [2, 3], [3], [1], [2])]
    

    If you want no duplicate elements in the resulting subsets, use this instead:

    >>> filter(lambda s: sorted(sum(s,[])) == sorted(lis1), powerset(lis2))
    [([1, 2], [3]), ([2, 3], [1]), ([3], [1], [2])]
    

    Both methods use sum(s, []) to flatten the nested lists and then compare those to the original elements using either set (all present, ignore duplicates) or sorted (all present, exact same count).