Reputation: 6619
I have a dictionary that looks like this:
a: [a]
b: [b, c]
c: [d, e, f]
The number of keys and the number of elements in each list is unknown beforehand.
I would like to be able to obtain all the possible combinations of the elements in every list. The output for the above dictionary would be something like this:
[a, d, b]
[a, e, c]
[a, f, b]
[a, d, c]
[a, e, b]
[a, f, c]
Order for both the lists in the list and the elements in the lists in the list (that's a mouthful) doesn't matter.
I tried a solution which I have posted an answer to, but I am curious to find out if there are more efficient solutions.
EDIT: Only one element can be taken from every key in the dictionary. Following the example above, you can't have [b d e]
as d e
is from c
.
Upvotes: 1
Views: 89
Reputation: 1979
Well. I understand the question and corrected my answer.
Make the list of values using list comprehension
>>> d = {"a": [1], "b": [2,3], "c": [4,5,6]}
>>> values = [v for k,v in d.items()]
>>> values
[[1], [4, 5, 6], [2, 3]]
Then use itertools.product which is equivalent to for-loop.
>>> for i in itertools.product(*l):
... print i
...
(1, 4, 2)
(1, 4, 3)
(1, 5, 2)
(1, 5, 3)
(1, 6, 2)
(1, 6, 3)
Upvotes: 3
Reputation: 6619
I came up with this:
def _gcd(a, b):
while b:
a, b = b, a % b
return a
def _lcm(a, b):
return a * b // _gcd(a, b)
def lcm(numbers):
return reduce(_lcm, numbers)
def combinations(dict):
lengths = []
for key in dict.keys():
lengths.append(len(dict[key]))
lcm_int = lcm(lengths)
for key in dict.keys():
values = []
length = len(dict[key])
for i in range(lcm_int):
values.append(dict[key][i%length])
dict[key] = values
combinations = []
for i in range(lcm_int):
values = []
for key in dict.keys():
values.append(dict[key][i])
combinations.append(values)
return combinations
This code finds the LCM of the lengths of all lists in the dictionary. It then expands each list to something like this:
[a] -> [a, a, a, a, a, a]
[b, c] -> [b, c, b, c, b, c]
[d, e, f] -> [d, e, f, d, e, f]
Afterwards, it takes the first element of every list and places it in a new list (a combination) and does the same for the rest of the elements.
Upvotes: 0