Reputation: 133
So I have some sets:
sets = [
{a1,a2}, #a set
{b1,b2}, #b set
{c1,c2}, #c set
...
]
And I need to get all possible combinations of all sizes... but only one element from each set.
[
{a1}, {b1}, ..., # all single
{a1, b1}, {a1, b2} ..., # all pairs
... # all combinations less than n
{a1,b1,c1 ... }, {a2,b1,c1 ... }, ..., # size n
]
At the moment I am using iter_tools' powerset on the union of all the sets then filtering, but this is incredibly slow when the sets get large.
large_set = union_all_sets(sets)
r = more_itertools.powerset(large_set)
r = filter_1(r)
I was wondering if there is a simple function for this that I don't know the name of? Or if anybody had any suggestions how I can avoid calling powerset on the large set?
Upvotes: 1
Views: 498
Reputation: 24280
You can build combinations of 1, then 2... n of your sets, and for each of these combinations, generate the cartesian product:
from itertools import product, combinations
sets = [
{"a1", "a2"}, #a set
{"b1", "b2"}, #b set
{"c1", "c2", "c3"} #c set
]
out = []
for size in range(1, len(sets)+1):
for combination in combinations(sets, r=size):
out.extend(set(p) for p in product(*combination))
print(out)
Output:
[{'a2'}, {'a1'}, {'b1'}, {'b2'}, {'c2'}, {'c1'}, {'c3'},
{'b1', 'a2'}, {'b2', 'a2'}, {'b1', 'a1'}, {'b2', 'a1'}, {'c2', 'a2'},
{'c1', 'a2'}, {'c3', 'a2'}, {'c2', 'a1'}, {'c1', 'a1'}, {'c3', 'a1'},
{'b1', 'c2'}, {'b1', 'c1'}, {'b1', 'c3'}, {'c2', 'b2'}, {'c1', 'b2'},
{'b2', 'c3'},
{'b1', 'c2', 'a2'}, {'b1', 'c1', 'a2'}, {'b1', 'c3', 'a2'}, {'c2', 'b2', 'a2'},
{'c1', 'b2', 'a2'}, {'b2', 'c3', 'a2'}, {'b1', 'c2', 'a1'}, {'b1', 'c1', 'a1'},
{'b1', 'c3', 'a1'}, {'c2', 'b2', 'a1'}, {'c1', 'b2', 'a1'}, {'b2', 'c3', 'a1'}]
Upvotes: 2