1

I want to convert this:

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

into this:

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

Basically reversing this dictionary. Also the values of the new dictionary should be in list form like shown.

I have already tried using the zip function, reversing through (v,k) but everytime I get the same error: "unhashable type list".

def reverse_dictionary(d):    
    reverse=list(zip(d.values(),d.keys()))
    return reverse

Output should be this:

{'liikuttaa': ['move'], 'piilottaa': ['hide'], 'salata': ['hide'], 'kuusi': ['six', 'fir']}
norok2
  • 25,683
  • 4
  • 73
  • 99
  • There's probably a one liner that can do this, but I'd rather write a loop. – Peter Wood Jul 19 '19 at 10:18
  • notice that you don't have `'liikuttaa'` in the original dict, but rather you have `['liikuttaa']`. Essentially, it's a list. does a dictionary allow a list as keys? (ps. the answer is no. that's the error you see) – Paritosh Singh Jul 19 '19 at 10:18
  • 3
    Possible duplicate of [Inverting a dictionary with list values](https://stackoverflow.com/questions/35491223/inverting-a-dictionary-with-list-values) – gpk27 Jul 19 '19 at 10:28

4 Answers4

5

You can use a defaultdict with a list:

from collections import defaultdict
from pprint import pprint

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

result = defaultdict(list)

for key, values in d.items():
    for value in values:
        result[value].append(key)

pprint(dict(result))

Output:

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

Or you can use a normal dict with setdefault:

result = {}

for key, values in d.items():
    for value in values:
        result.setdefault(value, []).append(key)
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
2

I would first create a generator that generators key, values pairs in the existing dictionary:

def pairs(d):
    for key in d:
        for value in d[key]:
            yield key, value

Then use defaultdict to create the reversed structure:

from collections import defaultdict
reversed_d = defaultdict(list)

for key, value in pairs(d):
    reversed_d[value].append(key)
RemcoGerlich
  • 30,470
  • 6
  • 61
  • 79
0

A nested list comprehension will do this:

{vv: k for k, v in d.items() for vv in v}

Edit

I misunderstood your requirement. This is better:

from collections import defaultdict
new_dict = defaultdict(list)
for k, v in d.items()
    for val in v:
        new_dict[k].append(v)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
0

This is not simple, dictionary reversing. You also need to access/create the inner list and populate it accordingly (while avoiding key clashing on the resulting dict).

One way of doing this is:

def reverse_dict_special(d):
    result = {}
    for k, vs in d.items():
        for v in vs:
            if v in result:
                result[v].append(k)
            else:
                result[v] = [k]
    return result

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

Note that this does not require the use of collections.defaultdictor using dict.setdefault() as proposed by @PeterWood. Indeed the proposed method seems to get to faster results then both the other two:

from collections import defaultdict

def reverse_dict_special2(d):
    result = defaultdict(list)
    for key, values in d.items():
        for value in values:
            result[value].append(key)
    return result


def reverse_dict_special3(d):
    result = {}
    for key, values in d.items():
        for value in values:
            result.setdefault(value, []).append(key)
    return result


%timeit reverse_dict_special(d)
# 1.22 µs ± 29.8 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%timeit reverse_dict_special2(d)
# 2.04 µs ± 44 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit reverse_dict_special3(d)
# 1.55 µs ± 18.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

(EDITED: I had misunderstood the question at first, and did not realize that the input inner lists may have had multiple items)

norok2
  • 25,683
  • 4
  • 73
  • 99