有没有任何简单的方法来交换值列表的python字典键值 我的字典就像是
d={1:[1,2,3,4],2:[2,3,4],5:[1,3,6,7]}
我想从中生成一个字典,如下面的
a={1:[1,5],2:[1,2],3:[1,2,5],4:[1,2],6:[5],7:[5]}
我用反向测试
dict(map(reversed, d.items())
它不会迭代并使用列表中的项创建键返回TypeError:unhashable type:'list'
我正在寻找可用于实现此目的的任何内联方法
答案 0 :(得分:3)
这将有效:
def revdict(d):
r = {}
for k in d:
for v in d[k]:
if v not in r:
r[v] = [k]
else:
r[v].append(k)
return r
然后你可以这样做:
d={1:[1,2,3,4],2:[2,3,4],5:[1,3,6,7]}
a = revdict(d)
print(a)
如果您想避免检查新密钥,可以使用defaultdict
,然后始终附加。
答案 1 :(得分:2)
你的方法不起作用,因为在这里你的目标是构建一个字典:
{[1,2,3,4]: 1, [2,3,4]: 2, [1,3,6,7]: 5}
但是因为列表是不可用的,所以这些不能用作键(而且它不是你打算构建的那样)。
您可能最好使用defaultdict
:
from collections import defaultdict
result = defaultdict(list)
for k, vs in d.items():
for v in vs:
result[v].append(k)
在此操作之后,result
是defaultdict
( vanilla dict
的子类),它将值列表中的项目映射到键(包含那个价值)。像:
>>> result
defaultdict(<class 'list'>, {1: [1, 5], 2: [1, 2], 3: [1, 2, 5], 4: [1, 2], 6: [5], 7: [5]})
您可以选择使用:
result = dict(result)
创建一个包含这些值的新词典(从而删除defaultdict
)。
请注意:
d
中列表中的项目应为 hashable 。答案 2 :(得分:0)
这不适合单线;通过称之为简单的逆转,你过度简化了你需要做的事情。
真正的反转只会将值映射到键而不是键值,您可以这样做(通过将列表轻微但必要的更改为元组):
>>> print dict((tuple(d[k]), k) for k in d)
{(1, 3, 6, 7): 5, (2, 3, 4): 2, (1, 2, 3, 4): 1}
你想要的东西要复杂得多,通常被称为dict的换位。
from operator import itemgetter as ig
from itertools import groupby
transposed_dict = dict((k, map(ig(1), v))
for k, v in groupby(
sorted((nk, k) for k in d for nk in d[k]),
key=ig(0)))
关于这一点并没有什么特别简单,虽然从概念上讲它并不太糟糕:
(nk, k) for k in d for nk in d[k]
从字典中创建扩展的关联列表,其中键和值已反转。
groupby
使用共同的第一个元素收集所有元组
(k, map(ig(1), v))
将具有共同第一个元素的元组收集到一个元组中:(1,1), (1,2) => (1, [1,2])
。
第3步中的元组用于构建新词典。
然而,使用Willem Van Onsem所示的简单的3行for
循环,你会好得多;该循环的本质是sorted
使用的生成器表达式;其他一切只是处理避免可变变量的尝试。并非所有事情都应该(或可以)简化为简单的单行。