给定一本这样的字典:

my_map = {'a': 1, 'b': 2}

如何将此映射颠倒得到:

inv_map = {1: 'a', 2: 'b'}

当前回答

我认为最好的方法是定义一个类。下面是一个“对称字典”的实现:

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中添加或删除值,并且您的反向字典将始终保持有效——如果您只是将整个字典反向一次,这是不正确的。

其他回答

这是另一种方法。

my_map = {'a': 1, 'b': 2}

inv_map= {}
for key in my_map.keys() :
    val = my_map[key]
    inv_map[val] = key

有很多答案,但没有找到任何干净的东西,以防我们谈论的是一个具有非唯一值的字典。

解决办法是:

from collections import defaultdict

inv_map = defaultdict(list) 
for k, v in my_map.items(): 
    inv_map[v].append(k)

例子:

如果初始dict my_map ={“c”:1、“d”:5,' ':5 b: 10}

然后,运行上面的代码将得到:

{5: ['a', 'd'], 1: ['c'], 10: ['b']}

非双射地图的快速功能性解决方案(值不唯一):

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要求的。

我们也可以使用defaultdict来反转一个有重复键的字典:

from collections import Counter, defaultdict

def invert_dict(d):
    d_inv = defaultdict(list)
    for k, v in d.items():
        d_inv[v].append(k)
    return d_inv

text = 'aaa bbb ccc ddd aaa bbb ccc aaa' 
c = Counter(text.split()) # Counter({'aaa': 3, 'bbb': 2, 'ccc': 2, 'ddd': 1})
dict(invert_dict(c)) # {1: ['ddd'], 2: ['bbb', 'ccc'], 3: ['aaa']}  

在这里看到的:

这种技术比使用dict.setdefault()的等效技术更简单、更快。

我会在python2中这样做。

inv_map = {my_map[x] : x for x in my_map}