869

给定这样的字典:

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

如何反转这张地图以获得:

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

32 回答 32

1254

Python 3+:

inv_map = {v: k for k, v in my_map.items()}

蟒蛇2:

inv_map = {v: k for k, v in my_map.iteritems()}
于 2009-01-27T15:24:56.603 回答
191

假设 dict 中的值是唯一的:

蟒蛇 3:

dict((v, k) for k, v in my_map.items())

蟒蛇2:

dict((v, k) for k, v in my_map.iteritems())
于 2009-01-27T14:50:22.757 回答
173

如果中的值my_map不是唯一的:

蟒蛇 3:

inv_map = {}
for k, v in my_map.items():
    inv_map[v] = inv_map.get(v, []) + [k]

蟒蛇2:

inv_map = {}
for k, v in my_map.iteritems():
    inv_map[v] = inv_map.get(v, []) + [k]
于 2009-01-27T21:33:26.483 回答
51

要在保留映射类型的同时执行此操作(假设它是一个dict或一个dict子类):

def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))
于 2009-11-05T10:41:30.830 回答
43

试试这个:

inv_map = dict(zip(my_map.values(), my_map.keys()))

(请注意,字典视图上的 Python 文档明确保证了这一点,.keys()并且.values()它们的元素以相同的顺序排列,这使得上述方法可以工作。)

或者:

inv_map = dict((my_map[k], k) for k in my_map)

或使用 python 3.0 的 dict 理解

inv_map = {my_map[k] : k for k in my_map}
于 2009-01-27T14:49:46.300 回答
37

另一种更实用的方式:

my_map = { 'a': 1, 'b':2 }
dict(map(reversed, my_map.items()))
于 2014-02-26T16:35:03.473 回答
17

我们还可以使用以下方法反转具有重复键的字典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().

于 2016-12-26T23:01:25.460 回答
15

这扩展了Robert的答案,适用于 dict 中的值不唯一的情况。

class ReversibleDict(dict):

    def reversed(self):
        """
        Return a reversed dict, with common values in the original dict
        grouped into a list in the returned dict.

        Example:
        >>> d = ReversibleDict({'a': 3, 'c': 2, 'b': 2, 'e': 3, 'd': 1, 'f': 2})
        >>> d.reversed()
        {1: ['d'], 2: ['c', 'b', 'f'], 3: ['a', 'e']}
        """

        revdict = {}
        for k, v in self.iteritems():
            revdict.setdefault(v, []).append(k)
        return revdict

实施受到限制,因为您不能使用reversed两次并取回原始文件。它本身不是对称的。它使用 Python 2.6 进行了测试。是我如何使用打印结果字典的用例。

如果您宁愿使用 a 而set不是 a list,并且可能存在无序的应用程序对此有意义,而不是setdefault(v, []).append(k)使用setdefault(v, set()).add(k).

于 2012-10-24T20:40:19.283 回答
7

列表和字典理解的结合。可以处理重复的键

{v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
于 2018-04-19T03:24:11.217 回答
6

例如,您有以下字典:

dict = {'a': 'fire', 'b': 'ice', 'c': 'fire', 'd': 'water'}

你想以这种倒置的形式得到它:

inverted_dict = {'fire': ['a', 'c'], 'ice': ['b'], 'water': ['d']}

第一个解决方案。要反转字典中的键值对,请使用for-loop 方法:

# Use this code to invert dictionaries that have non-unique values

inverted_dict = dict()
for key, value in dict.items():
    inverted_dict.setdefault(value, list()).append(key)

第二种解决方案。使用字典理解方法进行反转:

# Use this code to invert dictionaries that have unique values

inverted_dict = {value: key for key, value in dict.items()}

第三个解决方案。使用还原反转方法(依赖于第二种解决方案):

# Use this code to invert dictionaries that have lists of values

dict = {value: key for key in inverted_dict for value in my_map[key]}
于 2019-01-10T05:55:16.853 回答
5

字典值是一个集合的情况。像:

some_dict = {"1":{"a","b","c"},
        "2":{"d","e","f"},
        "3":{"g","h","i"}}

反过来想:

some_dict = {vi: k  for k, v in some_dict.items() for vi in v}

输出是这样的:

{'c': '1',
 'b': '1',
 'a': '1',
 'f': '2',
 'd': '2',
 'e': '2',
 'g': '3',
 'h': '3',
 'i': '3'}
于 2021-01-10T22:00:08.717 回答
4

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

一个解决方案是:

from collections import defaultdict

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

例子:

如果初始字典my_map = {'c': 1, 'd': 5, 'a': 5, 'b': 10}

然后,运行上面的代码将给出:

{5: ['a', 'd'], 1: ['c'], 10: ['b']}
于 2021-03-01T13:15:35.393 回答
2

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

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 中添加或删除值,并且您的逆向字典将始终保持有效 - 如果您只是将整个字典反转一次,则情况并非如此。

于 2014-09-28T06:50:44.103 回答
2

这可以处理非唯一值并保留独特案例的大部分外观。

inv_map = {v:[k for k in my_map if my_map[k] == v] for v in my_map.itervalues()}

对于 Python 3.x,替换itervaluesvalues.

于 2017-01-25T20:23:49.610 回答
2

我发现这个版本比具有 10000 个键的字典的公认版本快 10% 以上。

d = {i: str(i) for i in range(10000)}

new_d = dict(zip(d.values(), d.keys()))
于 2020-09-08T23:03:24.537 回答
2

我知道这个问题已经有很多很好的答案,但我想分享这个非常简洁的解决方案,它也可以处理重复值:

def dict_reverser(d):
    seen = set()
    return {v: k for k, v in d.items() if v not in seen or seen.add(v)}

这依赖于总是在 Python中set.add返回的事实。None

于 2021-01-14T14:29:22.557 回答
1

如果值不是唯一的,并且您有点铁杆:

inv_map = dict(
    (v, [k for (k, xx) in filter(lambda (key, value): value == v, my_map.items())]) 
    for v in set(my_map.values())
)

特别是对于大型字典,请注意,此解决方案的效率远低于Python reverse / invert a mapping的答案,因为它会循环items()多次。

于 2010-04-17T20:14:06.983 回答
1

除了上面建议的其他函数,如果你喜欢 lambdas:

invert = lambda mydict: {v:k for k, v in mydict.items()}

或者,您也可以这样做:

invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )
于 2013-04-09T19:20:58.913 回答
1

这是另一种方法。

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

inv_map= {}
for key in my_map.keys() :
    val = my_map[key]
    inv_map[val] = key
于 2020-12-03T23:07:45.107 回答
1
dict([(value, key) for key, value in d.items()])
于 2021-12-11T22:05:44.443 回答
0

非双射映射的快速函数解决方案(值不唯一):

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 需要排序。

于 2014-03-06T20:50:11.423 回答
0

试试这个 python 2.7/3.x

inv_map={};
for i in my_map:
    inv_map[my_map[i]]=i    
print inv_map
于 2014-07-25T09:31:58.790 回答
0

函数对于 list 类型的值是对称的;执行 reverse_dict(reverse_dict(dictionary)) 时,元组被转换为列表

def reverse_dict(dictionary):
    reverse_dict = {}
    for key, value in dictionary.iteritems():
        if not isinstance(value, (list, tuple)):
            value = [value]
        for val in value:
            reverse_dict[val] = reverse_dict.get(val, [])
            reverse_dict[val].append(key)
    for key, value in reverse_dict.iteritems():
        if len(value) == 1:
            reverse_dict[key] = value[0]
    return reverse_dict
于 2014-09-24T12:23:00.220 回答
0

由于字典在字典中需要一个唯一的键,而不是值,因此我们必须将反转的值附加到排序列表中,以包含在新的特定键中。

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
于 2016-01-09T01:26:12.090 回答
0

当前 python 3.x 版本的 lambda 解决方案:

d1 = dict(alice='apples', bob='bananas')
d2 = dict(map(lambda key: (d1[key], key), d1.keys()))
print(d2)

结果:

{'apples': 'alice', 'bananas': 'bob'}

此解决方案不检查重复项。

一些备注:

  • lambda 构造可以从外部范围访问 d1,因此我们只传入当前键。它返回一个元组。
  • dict() 构造函数接受一个元组列表。它还接受映射的结果,因此我们可以跳过转换为列表。
  • 该解决方案没有显式for循环。它还避免了list comprehension对数学不好的人使用 a ;-)
于 2020-06-16T15:03:18.993 回答
0

接受高度投票的答案开始If the values in my_map are not unique:,我遇到了一个问题,不仅值不是唯一的,而且它们是一个列表,列表中的每个项目再次由一个三个元素的列表:一个字符串值、一个数字和另一个数字。

例子:

mymap['key1']给你:

[('xyz', 1, 2),
 ('abc', 5, 4)]

我只想用键切换字符串值,将两个数字元素保持在同一个位置。你只需要另一个嵌套的 for 循环然后:

inv_map = {}
for k, v in my_map.items():
    for x in v:
        # with x[1:3] same as x[1], x[2]:
        inv_map[x[0]] = inv_map.get(x[0], []) + [k, x[1:3]]

例子:

inv_map['abc']现在给你:

[('key1', 1, 2),
 ('key1', 5, 4)]
于 2021-12-22T23:51:48.963 回答
-1

我会在 python 2 中这样做。

inv_map = {my_map[x] : x for x in my_map}
于 2017-04-26T14:28:34.130 回答
-1
def invertDictionary(d):
    myDict = {}
  for i in d:
     value = d.get(i)
     myDict.setdefault(value,[]).append(i)   
 return myDict
 print invertDictionary({'a':1, 'b':2, 'c':3 , 'd' : 1})

这将提供如下输出:{1: ['a', 'd'], 2: ['b'], 3: ['c']}

于 2017-08-30T10:11:43.783 回答
-1
  def reverse_dictionary(input_dict):
      out = {}
      for v in input_dict.values():  
          for value in v:
              if value not in out:
                  out[value.lower()] = []

      for i in input_dict:
          for j in out:
              if j in map (lambda x : x.lower(),input_dict[i]):
                  out[j].append(i.lower())
                  out[j].sort()
      return out

这段代码是这样的:

r = reverse_dictionary({'Accurate': ['exact', 'precise'], 'exact': ['precise'], 'astute': ['Smart', 'clever'], 'smart': ['clever', 'bright', 'talented']})

print(r)

{'precise': ['accurate', 'exact'], 'clever': ['astute', 'smart'], 'talented': ['smart'], 'bright': ['smart'], 'exact': ['accurate'], 'smart': ['astute']}
于 2017-12-18T16:11:44.013 回答
-2

没有完全不同的东西,只是从食谱中重写了一点食谱。它通过保留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.x 替换mapping.items()mapping.iteritems()

在我的机器上运行比这里的其他示例快一点

于 2016-08-02T18:08:53.137 回答
-2

我在循环'for'和方法'.get()'的帮助下写了这个,我将字典的名称'map'更改为'map1',因为'map'是一个函数。

def dict_invert(map1):
    inv_map = {} # new dictionary
    for key in map1.keys():
        inv_map[map1.get(key)] = key
    return inv_map
于 2016-08-05T19:47:24.360 回答
-2

如果值不是唯一的并且可能是哈希(一维):

for k, v in myDict.items():
    if len(v) > 1:
        for item in v:
            invDict[item] = invDict.get(item, [])
            invDict[item].append(k)
    else:
        invDict[v] = invDict.get(v, [])
        invDict[v].append(k)

如果您需要更深入地挖掘,则使用递归,那么只需一维:

def digList(lst):
    temp = []
    for item in lst:
        if type(item) is list:
            temp.append(digList(item))
        else:
            temp.append(item)
    return set(temp)

for k, v in myDict.items():
    if type(v) is list:
        items = digList(v)
        for item in items:
            invDict[item] = invDict.get(item, [])
            invDict[item].append(k)
    else:
        invDict[v] = invDict.get(v, [])
        invDict[v].append(k)
于 2017-01-10T10:37:35.730 回答