简体   繁体   中英

Extend dict from key/values pair to key/value pair in Python

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'}

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}

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM