在Python中将键值对扩展为键/值对

0 投票
2 回答
1543 浏览
提问于 2025-04-20 21:49
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 来存储值,而不是用 listappend 方法:

from collections import defaultdict
myNewDict = defaultdict(set)
for staff_id, names in myDict.items():
    for name in names:
        myNewDict[name].add(staff_id)

撰写回答