Reputation: 75
myDict = {'121': ['adrian', 'alex', 'peter'], '122': ['john', 'vic', 'bill']}
I want to 'extend' my dictionary so that each key/value pair consists of one value, instead of a list. Tried iterating with myDict.keys() and myDict.values() and construct a new dict, didnt work out (i'm quite new to python3). This is what I want to achieve:
myNewDict = {'121': 'adrian', '121': 'alex', '121': 'peter', '122': 'john', '122': 'vic', '122':'bill'}
Upvotes: 0
Views: 1867
Reputation: 37319
Based on comments above, here's how to invert the dict and allow multiple values for each key:
from collections import defaultdict
myNewDict = defaultdict(list)
for staff_id, names in myDict.items():
for name in names:
myNewDict[name].append(staff_id)
You might use a defaultdict
of set
and add
instead of list
and append
if order doesn't matter:
from collections import defaultdict
myNewDict = defaultdict(set)
for staff_id, names in myDict.items():
for name in names:
myNewDict[name].add(staff_id)
Upvotes: 0
Reputation: 51807
If you don't care about collisions being clobbered, here's a 1-line solution (plus import):
import functools
myDict = {'121': ['adrian', 'alex', 'peter'], '122': ['john', 'vic', 'bill']}
print(functools.reduce( lambda x,y: dict(x, **y), (dict(map(lambda x: (x,i), myDict[i])) for i in myDict)))
To break apart what this is doing:
# This is a generator that creates a new dictionary out of each key/valuelist
(dict(map(lambda val: (val,key), myDict[key])) for key in myDict)
# => {'adrian': '121', 'alex': '121': 'peter': '121'}
# => {'john': '122', 'bill': '122', 'vic': '122'}
Once you have that,then call
functools.reduce( lambda x,y: dict(x, **y), <generator here>)
Reduce takes a function and applies it
cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value.
dict(mydict, **yourdict)
combines dictionaries by way of argument unpacking.
Which means that this takes the first dictionary from the list, and combines it with the next dictionary in the list, and so-on and so-forth until all the dictionaries in the list have been combined into one grand dictionary.
All that being said, I'd probably do something like this instead:
inverted = dict((name, k) for k, v in myDict.items() for name in v)
Alternate syntax using a dictionary comprehension:
inverted = {name: k for k, v in myDict.items() for name in v}
Upvotes: 1