Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add multiple values to a key in a Python dictionary

I am trying to create a dictionary from the values in the name_num dictionary where the length of the list is the new key and the name_num dictionary key and value are the value. So:

name_num = {"Bill": [1,2,3,4], "Bob":[3,4,2], "Mary": [5, 1], "Jim":[6,17,4], "Kim": [21,54,35]}

I want to create the following dictionary:

new_dict = {4:{"Bill": [1,2,3,4]}, 3:{"Bob":[3,4,2], "Jim":[6,17,4], "Kim": [21,54,35]}, 2:{"Mary": [5, 1]}}

I've tried many variations, but this code gets me the closest:

for mykey in name_num:
    new_dict[len(name_num[mykey])] = {mykey: name_num[mykey]}

Output:

new_dict = {4:{"Bill": [1,2,3,4]}, 3:{"Jim":[6,17,4]}, 2:{"Mary": [5, 1]}}

I know I need to loop through the code somehow so I can add the other values to key 3.

like image 262
Oedipus Avatar asked Aug 29 '16 01:08

Oedipus


3 Answers

This is a good use case for defaultdict:

from collections import defaultdict
name_num = {
    'Bill': [1, 2, 3, 4],
    'Bob': [3, 4, 2],
    'Mary': [5, 1],
    'Jim': [6, 17, 4],
    'Kim': [21, 54, 35],
}

new_dict = defaultdict(dict)
for name, nums in name_num.items():
    new_dict[len(nums)][name] = nums

print(dict(new_dict))

Output:

{
    2: {'Mary': [5, 1]},
    3: {'Bob': [3, 4, 2], 'Jim': [6, 17, 4], 'Kim': [21, 54, 35]},
    4: {'Bill': [1, 2, 3, 4]}
}
like image 132
Karin Avatar answered Oct 18 '22 21:10

Karin


Dictionary, associative array or map (many names, basically the same functionality) property is that keys are unique.

The keys you wish to have, which are integers, are not unique if lengths are the same, that's why your code doesn't work. Putting a new value for existing key means replacing the old value.

You have to add key-value pairs to the existing value dictionaries.

for mykey in name_num:
    length = len(name_num[mykey])
    if length in new_dict: # key already present in new dictionary
        new_dict[length][mykey] = name_num[mykey]
    else:
        new_dict[length] = {mykey: name_num[mykey]}

should do the trick

like image 31
Jezor Avatar answered Oct 18 '22 21:10

Jezor


Just an alternative to others; you can sort by length and use itertools.groupby:

>>> result = {}
>>> f = lambda t: len(t[1])
>>> for length, groups in itertools.groupby(sorted(name_num.items(), key=f), key=f):
...     result[length] = dict((k, v) for k, v in groups)
>>> print result
{
    2: {'Mary': [5, 1]},
    3: {'Bob': [3, 4, 2], 'Jim': [6, 17, 4], 'Kim': [21, 54, 35]},
    4: {'Bill': [1, 2, 3, 4]}
}

In a worst case scenario where each inner list has a different length, this performs O(n^2) which is fairly inefficient compared to other solutions posted above.

like image 43
Ozgur Vatansever Avatar answered Oct 18 '22 19:10

Ozgur Vatansever