ShreyGrover
ShreyGrover

Reputation: 35

How to create a dictionary whose values are lists

I read a code in a book 'Think Python'. This code gets stuck at the inverse[val].[key] with an error:

'str' object has no attribute 'append''

Which makes sense as inverse[val] contains a string object. Here d is the input dictionary.

def invert_dict(d):
    inverse = dict()
    for key in d:
        val = d[key]
        if val not in inverse:
            inverse[val] = [key]
        else:
            inverse[val].append(key)
    return inverse

The input dictionary is {'a': 1, 'p': 1, 'r': 2, 't': 1, 'o': 1}

The expected output is {1: ['a', 'p', 't', 'o'], 2: ['r']}

How do I implement this, by modifying the given block of code?

Upvotes: 2

Views: 1031

Answers (4)

Vasilis G.
Vasilis G.

Reputation: 7846

You can also follow a different approach in which you take all values from your dictionary and match each value with the keys that have this value in the initial dictionary:

def invert_dict(d):
    values = set(d.values())
    inverse = dict((v,[k for k in d.keys() if d[k]==v]) for v in values)
    return inverse


inv = invert_dict({'a': 1, 'p': 1, 'r': 2, 't': 1, 'o': 1})
print(inv)

Output:

{1: ['a', 'p', 't', 'o'], 2: ['r']}

Upvotes: 0

Jundiaius
Jundiaius

Reputation: 7610

A one-liner using reduce:

inverted_dict = reduce((lambda inverted_dict, key: inverted_dict.setdefault(dd[key], []).append(key) or inverted_dict), d, {})

Output:

{1: ['t', 'o', 'p', 'a'], 2: ['r']}

Upvotes: 0

f-roche
f-roche

Reputation: 261

try this:

def invert_dict(data):
    inverse = {}
    for key, value in data.items():
        if value not in inverse:
            inverse[value] = [key]
        else:
            inverse[value].append(key)
    return inverse

Upvotes: 0

jpp
jpp

Reputation: 164623

You can use collections.defaultdict to create a dictionary of lists. Then append to dictionary values while iterating your input dictionary.

from collections import defaultdict

d_in = {'a': 1, 'p': 1, 'r': 2, 't': 1, 'o': 1}

d_out = defaultdict(list)

for k, v in d_in.items():
    d_out[v].append(k)

print(d_out)

defaultdict(<class 'list'>, {1: ['a', 'p', 't', 'o'], 2: ['r']})

Your code can be improved by iterating keys and values simultaneously via dict.items, instead of iterating keys and manually extracting the value. In addition, your indentation is incorrect. After resolving these issues:

def invert_dict(d):
    inverse = dict()
    for key, val in d.items():
        if val not in inverse:
            inverse[val] = [key]
        else:
            inverse[val].append(key)
    return inverse

Upvotes: 2

Related Questions