首页 文章

Python反向/反转映射

提问于
浏览
491

给出一个像这样的字典:

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

如何反转此 Map 以获得:

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

EDITOR NOTE: map 已更改为 my_map 以避免与内置函数 map 发生冲突 . 下面有些评论可能会受到影响 .

30 回答

  • 2

    加上我2美分的pythonic方式:

    inv_map = dict(map(reversed, my_map.items()))
    

    例:

    In [7]: my_map
    Out[7]: {1: 'one', 2: 'two', 3: 'three'}
    
    In [8]: inv_map = dict(map(reversed, my_map.items()))
    
    In [9]: inv_map
    Out[9]: {'one': 1, 'three': 3, 'two': 2}
    
  • 162

    列表与字典理解的结合 . 可以处理重复的键

    {v:[i for i in d.keys() if d[i] == v ] for k,v in d.items()}
    
  • 108

    如果值不是唯一的,那么你就是一个小硬核:

    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() .

  • 35

    试试这个:

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

    (注意the Python docs on dictionary views明确保证 .keys().values() 的元素顺序相同,这使得上述方法可以正常工作 . )

    或者:

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

    或使用python 3.0的字典理解

    inv_map = {my_map[k] : k for k in my_map}
    
  • 4

    另一个更实用的方式:

    my_map = { 'a': 1, 'b':2 }
    dict(map(reversed, my_map.items()))
    
  • 3

    这扩展了答案Python reverse / invert a mapping,适用于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进行测试 . Here是我用于打印结果字典的用例 .

    如果您更愿意使用 set 而不是 list ,并且有适合的应用程序,而不是 setdefault(v, []).append(k) ,请使用 setdefault(v, set()).add(k) .

  • 6

    对于Python 2.7.x

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

    对于Python 3:

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

    假设dict中的值是唯一的:

    dict((v, k) for k, v in my_map.iteritems())
    
  • -1

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

    inv_map = {}
    for k, v in my_map.iteritems():
        inv_map[v] = inv_map.get(v, [])
        inv_map[v].append(k)
    
  • 3
    def inverse_mapping(f):
        return f.__class__(map(reversed, f.items()))
    
  • 30

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

    from collections import Counter, defaultdict
    
    def invert_dict(d):
        d_inv = defaultdict(list)
        for k, v in c.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']}
    

    here

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

  • 1

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

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

    或者,你也可以这样做:

    invert = lambda mydict: dict( zip(mydict.values(), mydict.keys()) )
    
  • -3

    它处理非唯一值并保留了独特案例的大部分外观 .

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

    对于Python 3.x,将值替换为itervalues . 我不能相信这一点......它是由Icon Jack提出的 .

  • 0

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

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

  • 5

    使用zip

    inv_map = dict(zip(my_map.values(), my_map.keys()))
    
  • -5

    试试这个python 2.7 / 3.x.

    inv_map={};
    for i in my_map:
        inv_map[my_map[i]]=i    
    print inv_map
    
  • 0

    我会在python 2中这样做 .

    inv_map = {my_map[x] : x for x in my_map}
    
  • 0
    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']}

  • 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']}
    
  • 17

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

    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
    
  • -1

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

    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
    
  • 1

    不是完全不同的东西,只是Cookbook的一些重写食谱 . 通过保留 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.iteritems() 替换 mapping.items()

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

  • 0

    如果值不唯一,则可以是哈希(一维):

    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)
    
  • 0

    反转你的字典:

    dict_ = {"k0":"v0", "k1":"v1", "k2":"v1"}
    inversed_dict_ = {val: key for key, val in dict_.items()}
    
    print(inversed_dict_["v1"])
    
  • 0

    根据我对这个问题的评论 . 我认为对于Python2和Python 3都适用的最简单和一个班轮将是

    dict(zip(inv_map.values(), inv_map.keys()))
    
  • 1

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

    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
            )
        }
    

    理论上,这应该比在imperative solution中逐个添加到集合(或附加到列表)更快 .

    不幸的是,值必须是可排序的,groupby需要排序 .

  • 675

    我在循环'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
    
  • 5

    对于所有类型的字典,无论它们是否没有唯一值用作键,您都可以为每个值创建键列表

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

    这不是最好的解决方案,但它确实有效 . 假设我们要反转的词典是:

    dictionary = {'a':1,'b':2,'c':3},然后:

    dictionary = {'a': 1, 'b': 2, 'c': 3}
    reverse_dictionary = {}
    for index, val in enumerate(list(dictionary.values())):
        reverse_dictionary[val] = list(dictionary.keys())[index]
    

    reverse_dictionary的输出,应该是{1:'a',2:'b',3:'c'}

  • -3

    如果项目不是唯一的,试试这个:

    dict={}
         dict1={}
         num=int(raw_input(" how many numbers in dict?--> "))
         for i in range (0,num):
             key=raw_input(" enter key --> ")
             value=raw_input("enter value --> ")
             dict[key]=value
         keys=dict.keys()
         values=dict.values()
         for b in range (0,num):
             keys[b],values[b]=values[b],keys[b]
             dict1[keys[b]]=values[b]
         print keys
         print values
         print dict1
    

相关问题