Olba12
Olba12

Reputation: 335

Different combinations of a list with respect to a dictionary

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

Answers (3)

Thierry Lathuille
Thierry Lathuille

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

rajjix
rajjix

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

Ajax1234
Ajax1234

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

Related Questions