0

I'm trying to reverse a dictionary in Python

This is how it should work:

d={'move': ['liikuttaa'], 'hide': ['piilottaa', 'salata'], 'six': ['kuusi'], 'fir': ['kuusi']}
reverse_dictionary(d)
{'liikuttaa': ['move'], 'piilottaa': ['hide'], 'salata': ['hide'], 'kuusi': ['six', 'fir']}

Here is what I have come up with:

def reverse_dictionary(d):
    reversed = {value: key for (key, value) in d.items()}
    return reversed

def main():
    d = {'move': ['liikuttaa'], 'hide': ['piilottaa',
                                         'salata'], 'six': ['kuusi'], 'fir': ['kuusi']}
    print(reverse_dictionary(d))
  
if __name__ == "__main__":
    main()

But since the value is in a list, the output results in a TypeError: unhashable type: 'list'. Is there anything I can do to fix this?

Chi Le
  • 19
  • 6
  • 1
    Dictionary needs need to be immutable so you can use an integer, float, string, or Boolean as a dictionary key. However, list isn't immutable so you can't use it as a key. – Yoshikage Kira May 30 '21 at 05:32
  • Since each key in a dictionary is unique and hashable, each value must also be unique and hashable to reverse a dictionary.That's the reason you are getting this error. – Ashish Nautiyal May 30 '21 at 05:41
  • Check this answer :https://stackoverflow.com/questions/35491223/inverting-a-dictionary-with-list-values – Ashish Nautiyal May 30 '21 at 05:41
  • 1
    I assume you mean a dictionary to reverse the translations? – libby May 30 '21 at 05:48
  • @libby yup it's to reverse the translations but keep the list type the same – Chi Le May 30 '21 at 06:01

4 Answers4

1

This works:

from collections import defaultdict


def reverse_dictionary(d):
    reversed = defaultdict(list)
    for (key, array) in d.items():
        for value in array:
            reversed[value].append(key)
    return dict(reversed)
0

You may just have to brute force it:

reversed = {}
for english,translated in translation.items():
  for word in translated:
    if word in reversed:
      reversed[word].append(english)
    else:
      reversed[word] = [english]
libby
  • 585
  • 4
  • 15
0
newdict = {}

for key, val in d.items():
  if len(val) == 1:
     newdict[val[0]] = key
  else:
    for items in val:
       newdict[items] = key 

print(newdict)

One issue is that the last two will have the same key and you can't do that with a dictionary

marienbad
  • 1,461
  • 1
  • 9
  • 19
0

I observe that your dictionary is of synonyms, translating words from English (Language A) to Finnish (detected language in google translator say Language B).

So what you need is reverse the translation: Language B to Language A.


Case 1: Just reverse data structure without contextual meaning

If you simply put reverse the solution would not be dictionary which provides you translation at all.

i.e. "['piilottaa', 'salata']": "hide" or "piilottaa, salata": "hide" or ('piilottaa', 'salata')": "hide"

If you are simply looking for solution like above, tuple could be great option to you, as tuple is immutable and can be dictionary key as well. ()

def reverse_dictionary(d):
    res = {}
    for key, value in d.items():
        _val = tuple(value)
        res.setdefault(_val, []).append(key)
    return res

And your output would look like below:

{('liikuttaa',): ['move'],
 ('piilottaa', 'salata'): ['hide'],
 ('kuusi',): ['six', 'fir']}

Case 2: Contextually reversing translation

on the other hand, if you actually wish your solution to be as reveres dictionary like "piilottaa": ["hide"], "salata": ["hide"] contextually as well, use this:

def reverse_contextual_dictionary(d):
    res = {}
    for key, value in d.items():
        for _val in value:
            res.setdefault(_val, []).append(key)
    return res

And your output result would be as:

In [12]: d
Out[12]:
{'move': ['liikuttaa'],
 'hide': ['piilottaa', 'salata'],
 'six': ['kuusi'],
 'fir': ['kuusi']}

In [13]: reverse_contextual_dictionary(d)
Out[13]:
{'liikuttaa': ['move'],
 'piilottaa': ['hide'],
 'salata': ['hide'],
 'kuusi': ['six', 'fir']}
Gahan
  • 4,075
  • 4
  • 24
  • 44