在Python中将键值对扩展为键/值对
myDict = {'121': ['adrian', 'alex', 'peter'], '122': ['john', 'vic', 'bill']}
我想要“扩展”我的字典,让每个键/值对只包含一个值,而不是一个列表。我尝试用 myDict.keys() 和 myDict.values() 来遍历,然后构建一个新的字典,但没成功(我对 Python3 还很陌生)。这是我想要实现的目标:
myNewDict = {'121': 'adrian', '121': 'alex', '121': 'peter', '122': 'john', '122': 'vic', '122':'bill'}
2 个回答
1
如果你不在乎碰撞被覆盖,这里有一个一行的解决方案(加上导入):
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)))
接下来我们来拆解一下这个代码在做什么:
# 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'}
一旦你有了这个,就可以调用
functools.reduce( lambda x,y: dict(x, **y), <generator here>)
Reduce 是一个函数,它会把你给它的函数应用到序列的每个元素上,从左到右,这样就能把整个序列缩减成一个单一的值。
也就是说,它会把序列中的元素逐个处理,最后得到一个结果。
dict(mydict, **yourdict)
是通过 参数解包 来合并字典的。
这意味着它会先拿列表中的第一个字典,然后把它和下一个字典合并,依此类推,直到列表中的所有字典都合并成一个大的字典。
话虽如此,我可能会选择这样做:
inverted = dict((name, k) for k, v in myDict.items() for name in v)
使用字典推导的另一种语法:
inverted = {name: k for k, v in myDict.items() for name in v}
0
根据上面的评论,这里有一种方法可以反转字典,并且允许每个键有多个值:
from collections import defaultdict
myNewDict = defaultdict(list)
for staff_id, names in myDict.items():
for name in names:
myNewDict[name].append(staff_id)
如果不在乎顺序,你可以使用一个叫做 defaultdict
的东西,里面用 set
来存储值,而不是用 list
和 append
方法:
from collections import defaultdict
myNewDict = defaultdict(set)
for staff_id, names in myDict.items():
for name in names:
myNewDict[name].add(staff_id)