How to get all subsets of a set? (powerset)

前端 未结 28 2463
庸人自扰
庸人自扰 2020-11-22 05:18

Given a set

{0, 1, 2, 3}

How can I produce the subsets:

[set(),
 {0},
 {1},
 {2},
 {3},
 {0, 1},
 {0, 2},
 {0, 3},
 {1, 2}         


        
相关标签:
28条回答
  • 2020-11-22 05:33
    def powerset(lst):
        return reduce(lambda result, x: result + [subset + [x] for subset in result],
                      lst, [[]])
    
    0 讨论(0)
  • 2020-11-22 05:37

    There is a refinement of powerset:

    def powerset(seq):
        """
        Returns all the subsets of this set. This is a generator.
        """
        if len(seq) <= 0:
            yield []
        else:
            for item in powerset(seq[1:]):
                yield [seq[0]]+item
                yield item
    
    0 讨论(0)
  • 2020-11-22 05:38
    def get_power_set(s):
      power_set=[[]]
      for elem in s:
        # iterate over the sub sets so far
        for sub_set in power_set:
          # add a new subset consisting of the subset at hand added elem
          power_set=power_set+[list(sub_set)+[elem]]
      return power_set
    

    For example:

    get_power_set([1,2,3])
    

    yield

    [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
    
    0 讨论(0)
  • 2020-11-22 05:39

    The Python itertools page has exactly a powerset recipe for this:

    from itertools import chain, combinations
    
    def powerset(iterable):
        "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
        s = list(iterable)
        return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
    

    Output:

    >>> list(powerset("abcd"))
    [(), ('a',), ('b',), ('c',), ('d',), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd'), ('a', 'b', 'c'), ('a', 'b', 'd'), ('a', 'c', 'd'), ('b', 'c', 'd'), ('a', 'b', 'c', 'd')]
    

    If you don't like that empty tuple at the beginning, you can just change the range statement to range(1, len(s)+1) to avoid a 0-length combination.

    0 讨论(0)
  • 2020-11-22 05:40

    Just a quick power set refresher !

    Power set of a set X, is simply the set of all subsets of X including the empty set

    Example set X = (a,b,c)

    Power Set = { { a , b , c } , { a , b } , { a , c } , { b , c } , { a } , { b } , { c } , { } }

    Here is another way of finding power set:

    def power_set(input):
        # returns a list of all subsets of the list a
        if (len(input) == 0):
            return [[]]
        else:
            main_subset = [ ]
            for small_subset in power_set(input[1:]):
                main_subset += [small_subset]
                main_subset += [[input[0]] + small_subset]
            return main_subset
    
    print(power_set([0,1,2,3]))
    

    full credit to source

    0 讨论(0)
  • 2020-11-22 05:40

    Almost all of these answers use list rather than set, which felt like a bit of a cheat to me. So, out of curiosity I tried to do a simple version truly on set and summarize for other "new to Python" folks.

    I found there's a couple oddities in dealing with Python's set implementation. The main surprise to me was handling empty sets. This is in contrast to Ruby's Set implementation, where I can simply do Set[Set[]] and get a Set containing one empty Set, so I found it initially a little confusing.

    To review, in doing powerset with sets, I encountered two problems:

    1. set() takes an iterable, so set(set()) will return set() because the empty set iterable is empty (duh I guess :))
    2. to get a set of sets, set({set()}) and set.add(set) won't work because set() isn't hashable

    To solve both issues, I made use of frozenset(), which means I don't quite get what I want (type is literally set), but makes use of the overall set interace.

    def powerset(original_set):
      # below gives us a set with one empty set in it
      ps = set({frozenset()}) 
      for member in original_set:
        subset = set()
        for m in ps:
          # to be added into subset, needs to be
          # frozenset.union(set) so it's hashable
          subset.add(m.union(set([member]))
        ps = ps.union(subset)
      return ps
    

    Below we get 2² (16) frozensets correctly as output:

    In [1]: powerset(set([1,2,3,4]))
    Out[2]:
    {frozenset(),
     frozenset({3, 4}),
     frozenset({2}),
     frozenset({1, 4}),
     frozenset({3}),
     frozenset({2, 3}),
     frozenset({2, 3, 4}),
     frozenset({1, 2}),
     frozenset({2, 4}),
     frozenset({1}),
     frozenset({1, 2, 4}),
     frozenset({1, 3}),
     frozenset({1, 2, 3}),
     frozenset({4}),
     frozenset({1, 3, 4}),
     frozenset({1, 2, 3, 4})}
    

    As there's no way to have a set of sets in Python, if you want to turn these frozensets into sets, you'll have to map them back into a list (list(map(set, powerset(set([1,2,3,4])))) ) or modify the above.

    0 讨论(0)
提交回复
热议问题