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}
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 set
s, I encountered two problems:
set()
takes an iterable, so set(set())
will return set()
because the empty set iterable is empty (duh I guess :))set({set()})
and set.add(set)
won't work because set()
isn't hashableTo 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) frozenset
s 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 set
s in Python, if you want to turn these frozenset
s into set
s, you'll have to map them back into a list
(list(map(set, powerset(set([1,2,3,4]))))
) or modify the above.