20

I would like to write a function that receives a dictionary as input argument and returns a reverse of the input dictionary where the values of the original dictionary are used as keys for the returned dictionary and the keys of the original dictionary are used as value for the returned dictionary as explained below:

dict = {'Accurate': ['exact', 'precise'], 
        'exact': ['precise'], 
        'astute': ['Smart', 'clever'], 
        'smart': ['clever', 'bright', 'talented']}

to

dict = {'precise': ['accurate', 'exact'], 
        'clever': ['astute', 'smart'], 
        'talented': ['smart'], 
        'bright': ['smart'],
        'exact': ['accurate'],
        'smart': ['astute']}

The list of values in the returned dictionary should be sorted in ascending order. Capitalization does not matter. This means that all the words should be converted to lower case letters. For example the word "Accurate" is capitalized in the original dictionary but in the returned dictionary it is written with all lower case letters.

#My code is:
from collections import defaultdict
def reverse_dictionary(input_dict):
   d = defaultdict(list)
   for v,k in input_dict.items():
       d[k].append(v)
       return d

But it returns this error though:

Error in evaluating function:
TypeError at line 6
unhashable type: 'list'
CristiFati
  • 38,250
  • 9
  • 50
  • 87
Utsav Maniar
  • 251
  • 1
  • 2
  • 6
  • 3
    The problem is that you cannot use any object as a key -- these objects must be immutable so their hash value does not change after they're added to the dictionary. In your case, lists are mutable, so they cannot be used as keys. You could convert them to tuples instead. – Frédéric Hamidi Mar 11 '16 at 16:42
  • 2
    Welcome to StackExchange! It might be helpful to give more thought to this problem. For example, why would `'Accurate': ['exact', 'precise']` become `'precise': ['accurate', 'exact']` instead of `'exact': ['accurate', 'precise']`? As far as your error message is concerned, a list cannot be your dict key, but I think the bigger problem is that you task needs to be clarified. – Daniel Standage Mar 11 '16 at 16:44
  • Also, dictionaries cannot be sorted. – Farhan.K Mar 11 '16 at 16:46
  • 1
    @FrédéricHamidi He is *trying* to use strings as keys, not lists. He just isn't doing it right. – zondo Mar 11 '16 at 16:57
  • Seems pretty clear to me. The content of the values become the keys, and the keys get added to the values, so `{'a': ['b', 'c']}` becomes `{'b': ['a'], 'c': ['a']}`. @DanielStandage, @SteinarLima – Vincent Savard Mar 11 '16 at 17:00
  • AH, I get it @DanielStandage - like I said, I can be a bit slow from time to time.. Hehe :-) – Steinar Lima Mar 11 '16 at 17:10

5 Answers5

16

You can do it very simply like this:

newdict = {}
for key, value in olddict.items():
    for string in value:
        newdict.setdefault(string, []).append(key)
zondo
  • 19,901
  • 8
  • 44
  • 83
5

I would begin by swapping the keys/values using a default dict:

output_dict = defaultdict(list)
for key, values in input_dict.items():
    for value in values:
        output_dict[value.lower()].append(key.lower())

And finally sorting:

for key, values in output_dict.items():
    output_dict[key] = sorted(values)
DaveBensonPhillips
  • 3,134
  • 1
  • 20
  • 32
1

Use a dict comprehension!

>>> evil_petting_zoo = {'bear':3, 'crocodile':1,'kangaroo':2,'goat':0}
>>> evil_petting_zoo.items()

dict_items([('bear', 3), ('crocodile', 1), ('kangaroo', 2), ('goat', 0)])

>>> {i[1]:i[0] for i in evil_petting_zoo.items()}

{3: 'bear', 1: 'crocodile', 2: 'kangaroo', 0: 'goat'}

TL;DR:

{i[1]:i[0] for i in myDictionary.items()}
Zach Estela
  • 1,282
  • 1
  • 8
  • 10
1

For the love of functional programming, here’s fun way:

from itertools import product
from more_itertools import map_reduce, flatten

olddict =  {'Accurate': ['exact', 'precise'], 
        'exact': ['precise'], 
        'astute': ['Smart', 'clever'], 
        'smart': ['clever', 'bright', 'talented']}

value_key_pairs = flatten(product(v,(k,)) for k,v in olddict.items())
out = map_reduce(value_key_pairs, lambda k:k[0].lower(), lambda k:k[1].lower())

assert dict(out) == {'exact': ['accurate'], 'precise': ['accurate', 'exact'], 'smart': ['astute'], 'clever': ['astute', 'smart'], 'bright': ['smart'], 'talented': ['smart']}

Matthias
  • 11
  • 2
-2

How I reverse a dict:

def reverse(org):
    return {v: k for k, v in org.items()}

print(reverse({1: 'a', 2: 'b'}))
# {'a': 1, 'b': 2}
wulfgarpro
  • 6,666
  • 12
  • 69
  • 110