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

前端 未结 28 2779
庸人自扰
庸人自扰 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: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.

提交回复
热议问题