1

I need to inverse a dictionary so that each old value will now be a key and the old keys will be the new values.

The trick is that there could be multiple values that are the same in the old dictionary so I need each value in the new dictionary to be a list, and if there were identical values in the old dictionary then they both will be in the list of the value of the new dictionary.

for example: the dictionary {"python" : 1, "is" : 1, "cool" : 2}

would end up as: {1 : ["python", "is"], 2 : ["cool"]}

this is what I tried:

def inverse_dict(my_dict):
    new_dict = {}
    values_list = list(my_dict.values())
    new_dict = new_dict.fromkeys(values_list)
    for key in new_dict:
        new_dict[key] = []
    for old_key in my_dict:
        new_dict[my_dict[old_key]] = list(new_dict[my_dict[old_key]]).append(old_key)
    return new_dict

Would greatly appreciate any help with my approach (and better approaches to the problem) as I am very new to Python, thanks!

  • Does this answer your question? [In-place dictionary inversion in Python](https://stackoverflow.com/questions/3418189/in-place-dictionary-inversion-in-python) – quamrana Oct 09 '20 at 20:11

3 Answers3

1

You can use dict.setdefault check if a key exists in the dictionary and if not, create new value (in this case empty list []):

d =  {"python" : 1, "is" : 1, "cool" : 2}

reversed_d = {}
for k, v in d.items():
    reversed_d.setdefault(v, []).append(k)

print(reversed_d)

Prints:

{1: ['python', 'is'], 2: ['cool']}

This can be more explicitly rewritten as:

d =  {"python" : 1, "is" : 1, "cool" : 2}

reversed_d = {}
for k, v in d.items():
    if v not in reversed_d:
        reversed_d[v] = [k]
    else:
        reversed_d[v].append(k)

print(reversed_d)
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
1

You can use a defaultdict to avoid the pre-fill step

from collections import defaultdict

def inverse_dict(my_dict: dict):
    new_dict = defaultdict(list)
    for k, v in my_dict.items():
        new_dict[v].append(k)
    return new_dict
azro
  • 53,056
  • 7
  • 34
  • 70
0

Though I prefer @azro's answer with the default dict, another solution is doing it with dictionary and list comprehensions.

It looks like this:

{value : [key for key in my_dict if my_dict[key] == value] for value in set(my_dict.values())}

What it does is runs over the values of the dictionary without duplicates - set(my_dict.values()).

It builds every value as a key (because it's on the left side of the ":").

And its value is a list of the keys that point to that value - [key for key in my_dict if my_dict[key] == value].

Shlomo Fel
  • 196
  • 1
  • 1
  • 8