用列表值反转字典
Inverting a dictionary with list values
所以,我将这个索引作为字典。
index = {'Testfil2.txt': ['nisse', 'hue', 'abe', 'pind'], 'Testfil1.txt': ['hue', 'abe',
'tosse', 'svend']}
我需要反转索引,这样它将成为一个字典,其中重复的值合并到一个键中,两个原始键作为值,如下所示:
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
它适用于简单的 key:value 对
但是,当我尝试使用具有列表作为值的字典的函数时,例如我的 index
我收到此错误消息:
invert_dict(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'
我已经搜索了一个小时来寻找解决方案,这本书没有帮助,我怀疑我可以以某种方式使用元组,但我不确定如何使用。有帮助吗?
您不能将 list
对象用作字典键,因为它们应该是可哈希对象。您可以遍历您的项目并使用 dict.setdefault
方法来创建预期结果:
>>> new = {}
>>>
>>> for k,value in index.items():
... for v in value:
... new.setdefault(v,[]).append(k)
...
>>> new
{'hue': ['Testfil2.txt', 'Testfil1.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil2.txt', 'Testfil1.txt'], 'tosse': ['Testfil1.txt'], 'pind': ['Testfil2.txt'], 'nisse': ['Testfil2.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)
>>> new
defaultdict(<type 'list'>, {'hue': ['Testfil2.txt', 'Testfil1.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil2.txt', 'Testfil1.txt'], 'tosse': ['Testfil1.txt'], 'pind': ['Testfil2.txt'], 'nisse': ['Testfil2.txt']})
我已经试过了,你想使用 val not in inverse
,但如果是 "list is in a dict",则无法检查。 (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
我的字典逆向解决方案。但是,它创建了一个新字典 new_dic
:
new_dic = {}
for k,v in index.items():
for x in v:
new_dic.setdefault(x,[]).append(k)
输出:
{'tosse': ['Testfil1.txt'], 'nisse': ['Testfil2.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil1.txt', 'Testfil2.txt'], 'pind': ['Testfil2.txt'], 'hue': ['Testfil1.txt', 'Testfil2.txt']}
作为嵌套理解:
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))
使用解包运算符 *
和嵌套压缩的两个线性解决方案。
for k,v in old_dict.items():
new_dict = {**new_dict,**{vi:k for vi in v}}
所以,我将这个索引作为字典。
index = {'Testfil2.txt': ['nisse', 'hue', 'abe', 'pind'], 'Testfil1.txt': ['hue', 'abe',
'tosse', 'svend']}
我需要反转索引,这样它将成为一个字典,其中重复的值合并到一个键中,两个原始键作为值,如下所示:
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
它适用于简单的 key:value 对
但是,当我尝试使用具有列表作为值的字典的函数时,例如我的 index
我收到此错误消息:
invert_dict(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'
我已经搜索了一个小时来寻找解决方案,这本书没有帮助,我怀疑我可以以某种方式使用元组,但我不确定如何使用。有帮助吗?
您不能将 list
对象用作字典键,因为它们应该是可哈希对象。您可以遍历您的项目并使用 dict.setdefault
方法来创建预期结果:
>>> new = {}
>>>
>>> for k,value in index.items():
... for v in value:
... new.setdefault(v,[]).append(k)
...
>>> new
{'hue': ['Testfil2.txt', 'Testfil1.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil2.txt', 'Testfil1.txt'], 'tosse': ['Testfil1.txt'], 'pind': ['Testfil2.txt'], 'nisse': ['Testfil2.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)
>>> new
defaultdict(<type 'list'>, {'hue': ['Testfil2.txt', 'Testfil1.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil2.txt', 'Testfil1.txt'], 'tosse': ['Testfil1.txt'], 'pind': ['Testfil2.txt'], 'nisse': ['Testfil2.txt']})
我已经试过了,你想使用 val not in inverse
,但如果是 "list is in a dict",则无法检查。 (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
我的字典逆向解决方案。但是,它创建了一个新字典 new_dic
:
new_dic = {}
for k,v in index.items():
for x in v:
new_dic.setdefault(x,[]).append(k)
输出:
{'tosse': ['Testfil1.txt'], 'nisse': ['Testfil2.txt'], 'svend': ['Testfil1.txt'], 'abe': ['Testfil1.txt', 'Testfil2.txt'], 'pind': ['Testfil2.txt'], 'hue': ['Testfil1.txt', 'Testfil2.txt']}
作为嵌套理解:
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))
使用解包运算符 *
和嵌套压缩的两个线性解决方案。
for k,v in old_dict.items():
new_dict = {**new_dict,**{vi:k for vi in v}}