用列表值反转字典
- 2025-01-10 08:47:00
- admin 原创
- 100
问题描述:
我有这个索引作为一个字典。
index = {
'Testfil2.txt': ['nisse', 'hue', 'abe', 'pind'],
'Testfil1.txt': ['hue', 'abe', 'tosse', 'svend']}
我需要反转索引,这样它将是一个字典,其中重复的值合并为一个键,并以 2 个原始键作为值,如下所示:
inverse = {
'nisse': ['Testfil2.txt'],
'hue': ['Testfil2.txt', 'Testfil1.txt'],
'abe': ['Testfil2.txt', 'Testfil1.txt'],
'pind': ['Testfil2.txt'],
'tosse': ['Testfil1.txt'],
'svend': ['Testfil1.txt']}
我的教科书有这个反转字典的功能:
def invert_dict(d):
inverse = dict()
for key in d:
val = d[key]
if val not in inverse:
inverse[val] = [key]
else:
inverse[val].append(key)
return inverse
它对于简单的键:值对工作得很好,但是,当我尝试使用具有列表作为值的字典(例如我的)时index
,我收到此错误消息:
Traceback (most recent call last):
File "<pyshell#153>", line 1, in <module>
invert_dict(index)
File "<pyshell#150>", line 5, in invert_dict
if val not in inverse:
TypeError: unhashable type: 'list'
这本书没有帮助,我怀疑我可以以某种方式使用元组,但我不确定如何。
解决方案 1:
我对反转字典的解决方案。
inverse = {}
for k,v in index.items():
for x in v:
inverse.setdefault(x, []).append(k)
输出:
{'nisse': ['Testfil2.txt'],
'hue': ['Testfil2.txt', 'Testfil1.txt'],
'abe': ['Testfil2.txt', 'Testfil1.txt'],
'pind': ['Testfil2.txt'],
'tosse': ['Testfil1.txt'],
'svend': ['Testfil1.txt']}
解决方案 2:
我已经尝试过了,你想使用val not in inverse
,但无法检查“列表是否在字典中”。 (val
是一个列表)
对于您的代码,一个简单的更改就可以实现您想要的效果:
def invert_dict(d):
inverse = dict()
for key in d:
# Go through the list that is saved in the dict:
for item in d[key]:
# Check if in the inverted dict the key exists
if item not in inverse:
# If not create a new list
inverse[item] = [key]
else:
inverse[item].append(key)
return inverse
解决方案 3:
作为嵌套理解:
inverse = { v: k for k, l in index.items() for v in l }
或者更清楚地说:
inverse = {
new_key: index_key #body
for index_key, index_value in index.items() #outer loop
for new_key in index_value #inner loop
}
大致相当于:
new_keys = []
new_values = []
for index_key, index_value in index.items():
for new_key in index_value:
new_keys.append(new_key)
new_values.append(index_key)
inverse = dict(zip(new_keys,new_values))
解决方案 4:
您不能使用list
对象作为字典键,因为它们应该是可哈希的对象。您可以循环遍历您的项目并使用dict.setdefault
方法来创建预期结果:
new = {}
for k,value in index.items():
for v in value:
new.setdefault(v, []).append(k)
结果:
{'nisse': ['Testfil2.txt'],
'hue': ['Testfil2.txt', 'Testfil1.txt'],
'abe': ['Testfil2.txt', 'Testfil1.txt'],
'pind': ['Testfil2.txt'],
'tosse': ['Testfil1.txt'],
'svend': ['Testfil1.txt']}
如果您正在处理更大的数据集,则拒绝在每次调用setdefault()
方法时创建一个空列表,您可以使用该方法collections.defaultdict()
,当遇到新键时它将调用缺少的函数。
from collections import defaultdict
new = defaultdict(list)
for k,value in index.items():
for v in value:
new[v].append(k)
结果:
defaultdict(<type 'list'>,
{'nisse': ['Testfil2.txt'],
'hue': ['Testfil2.txt', 'Testfil1.txt'],
'abe': ['Testfil2.txt', 'Testfil1.txt'],
'pind': ['Testfil2.txt'],
'tosse': ['Testfil1.txt'],
'svend': ['Testfil1.txt']})
解决方案 5:
这是一个使用理解加法set
来删除重复项的变体。
def invert_setdict(setdict):
inverse = {}
vk = [(v, k) for k, vs in index.items() for v in vs]
for k, v in vk:
inverse.setdefault(k, set()).add(v)
return inverse
例子
>>> index = {
... 'Testfil2.txt': ['nisse', 'hue', 'abe', 'pind'],
... 'Testfil1.txt': ['hue', 'abe', 'tosse', 'svend']}
>>> inverse = invert_setdict(index)
>>> inverse
{'nisse': {'Testfil2.txt'},
'hue': {'Testfil1.txt', 'Testfil2.txt'},
'abe': {'Testfil1.txt', 'Testfil2.txt'},
'pind': {'Testfil2.txt'},
'tosse': {'Testfil1.txt'},
'svend': {'Testfil1.txt'}}
如果要将设置值转换为列表:
>>> inverse = {k:list(v) for k, v in inverse.items()}
解决方案 6:
*
使用解包运算符和嵌套压缩的两行解决方案。
for k,v in old_dict.items():
new_dict = {**new_dict,**{vi:k for vi in v}}
相关推荐
热门文章
项目管理软件有哪些?
热门标签
云禅道AD