给定一本这样的字典:
my_map = {'a': 1, 'b': 2}
如何将此映射颠倒得到:
inv_map = {1: 'a', 2: 'b'}
给定一本这样的字典:
my_map = {'a': 1, 'b': 2}
如何将此映射颠倒得到:
inv_map = {1: 'a', 2: 'b'}
当前回答
另一种更实用的方法是:
my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
其他回答
不是完全不同的东西,只是从食谱中重写了一点。它通过保留setdefault方法进一步优化,而不是每次通过实例获取它:
def inverse(mapping):
'''
A function to inverse mapping, collecting keys with simillar values
in list. Careful to retain original type and to be fast.
>> d = dict(a=1, b=2, c=1, d=3, e=2, f=1, g=5, h=2)
>> inverse(d)
{1: ['f', 'c', 'a'], 2: ['h', 'b', 'e'], 3: ['d'], 5: ['g']}
'''
res = {}
setdef = res.setdefault
for key, value in mapping.items():
setdef(value, []).append(key)
return res if mapping.__class__==dict else mapping.__class__(res)
设计为在CPython 3下运行。X表示2。用mapping.iteritems()替换mapping.items()
在我的机器上运行得比这里的其他例子快一些
与值不同,字典需要在字典中有一个唯一的键,因此我们必须将反向的值附加到一个sort列表中,以便包含在新的特定键中。
def r_maping(dictionary):
List_z=[]
Map= {}
for z, x in dictionary.iteritems(): #iterate through the keys and values
Map.setdefault(x,List_z).append(z) #Setdefault is the same as dict[key]=default."The method returns the key value available in the dictionary and if given key is not available then it will return provided default value. Afterward, we will append into the default list our new values for the specific key.
return Map
我认为最好的方法是定义一个类。下面是一个“对称字典”的实现:
class SymDict:
def __init__(self):
self.aToB = {}
self.bToA = {}
def assocAB(self, a, b):
# Stores and returns a tuple (a,b) of overwritten bindings
currB = None
if a in self.aToB: currB = self.bToA[a]
currA = None
if b in self.bToA: currA = self.aToB[b]
self.aToB[a] = b
self.bToA[b] = a
return (currA, currB)
def lookupA(self, a):
if a in self.aToB:
return self.aToB[a]
return None
def lookupB(self, b):
if b in self.bToA:
return self.bToA[b]
return None
如果需要,删除和迭代方法很容易实现。
这种实现比颠倒整个字典(这似乎是本页上最流行的解决方案)更有效。更不用说,您可以随心所欲地从SymDict中添加或删除值,并且您的反向字典将始终保持有效——如果您只是将整个字典反向一次,这是不正确的。
非双射地图的快速功能性解决方案(值不唯一):
from itertools import imap, groupby
def fst(s):
return s[0]
def snd(s):
return s[1]
def inverseDict(d):
"""
input d: a -> b
output : b -> set(a)
"""
return {
v : set(imap(fst, kv_iter))
for (v, kv_iter) in groupby(
sorted(d.iteritems(),
key=snd),
key=snd
)
}
理论上,这应该比命令式解决方案中那样逐个添加到集合(或添加到列表)更快。
不幸的是,值必须是可排序的,排序是由groupby要求的。
如果my_map中的值不是唯一的:
Python 3:
inv_map = {}
for k, v in my_map.items():
inv_map[v] = inv_map.get(v, []) + [k]
Python 2:
inv_map = {}
for k, v in my_map.iteritems():
inv_map[v] = inv_map.get(v, []) + [k]