Reputation: 335
Lets say I have a list
my_list = [a, b, c]
and a dictionary
my_dict = dict({a:a_prime, b:b_prime, c:c_prime})
where all letter, letter_prime are integers. How can I find all combinations of creating unique lists with respect to the dictionary? With my example above I'd like a function that takes [a,b,c], my_dict as input
magic_function([a,b,c], my_dict)
.
.
.
return [[a_prime, b, c], [a, b_prime, c], [a, b, c_prime], [a_prime, b_prime, c], [a_prime, b, c_prime], [a, b_prime, c_prime], [a_prime, b_prime, c_prime]]
With unique im refeering too:
I consider [a_prime,b,c], [b,c, a_prime] to be equal, i.e. order doesnt mather.
And that it might be that some combinations are the same e.g. that [a_prime, b, c] turns out to be equal too [a, b_prime, c_prime]. It would be good then if only one of these are returned.
Upvotes: 1
Views: 45
Reputation: 24232
You can create all possible masks telling if we choose the key or corresponding value in the dict :
from itertools import product
my_dict = {'a': 'a_prime', 'b': 'b_prime', 'c': 'c_prime'}
def magic(keys):
out = []
for key_or_val in product([True, False], repeat=len(keys)):
out.append([key if k_v else my_dict[key] for key, k_v in zip(keys, key_or_val)])
return out
print(magic(['a', 'b', 'c']))
# [['a', 'b', 'c'], ['a', 'b', 'c_prime'], ['a', 'b_prime', 'c'], ['a', 'b_prime', 'c_prime'],
# ['a_prime', 'b', 'c'], ['a_prime', 'b', 'c_prime'], ['a_prime', 'b_prime', 'c'],
# ['a_prime', 'b_prime', 'c_prime']]
If you only want unique values, just use a set:
uniques = set(tuple(combination) for combination in magic(['a', 'b', 'c']))
Upvotes: 3
Reputation: 169
my_list = ["a", "b", "c"]
my_dict = dict({"a": "a_prime", "b": "b_prime", "c": "c_prime"})
From the example above I noticed you don't want to have key value pairs in same output so we separate them by making collections. and when creating our collection we will choose either key or value for every possible combination.
my_coll = [[key, my_dict[key]] for key in my_list]
Output:
>> [['a', 'a_prime'], ['b', 'b_prime'], ['c', 'c_prime']]
Finally we can use itertools product to get the desrired output as mentioned by your example.
from itertools import product
combinations = [list(x) for x in product(*my_coll)]
Output:
>> [['a', 'b', 'c'], ['a', 'b', 'c_prime'], ['a', 'b_prime', 'c'], ['a', 'b_prime', 'c_prime'], ['a_prime', 'b', 'c'], ['a_prime', 'b', 'c_prime'], ['a_prime', 'b_prime', 'c'], ['a_prime', 'b_prime', 'c_prime']]
Upvotes: 0
Reputation: 71451
You can use recursion with a generator:
my_list = ['a', 'b', 'c']
def combos(d, c = []):
if len(c) == len(my_list):
yield c
elif d:
yield from combos(d[1:], c+[d[0]])
yield from combos(d[1:], c+[f'{d[0]}_prime'])
print(list(combos(my_list)))
Output:
[['a', 'b', 'c'], ['a', 'b', 'c_prime'], ['a', 'b_prime', 'c'], ['a', 'b_prime', 'c_prime'], ['a_prime', 'b', 'c'], ['a_prime', 'b', 'c_prime'], ['a_prime', 'b_prime', 'c'], ['a_prime', 'b_prime', 'c_prime']]
Upvotes: 1