反转字典映射

1030

假设有如下字典:

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

如何反转该地图以获得以下结果:
inv_map = {1: 'a', 2: 'b'}
33个回答

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


通过使用dict.items(或在Python 2中使用iteritems)同时迭代键值对比单独提取每个值更有效率。此外,您在重复他人答案的回答中没有添加任何解释。 - jpp

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

0

参考得票最高的答案 如果my_map中的值不唯一:,我遇到了一个问题,不仅值不唯一,而且它们是一个列表,列表中的每个项目又由三个元素的列表组成:一个字符串值、一个数字和另一个数字。

例如:

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

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


1
“理论上,这应该比逐个添加到集合(或附加到列表)更快。” - 不。在原始字典中给定n个元素,由于需要对字典的项目进行排序,因此您的方法具有O(n log n)的时间复杂度,而天真的命令式方法具有O(n)的时间复杂度。就我所知,在实践中,您的方法可能更快,直到出现荒谬的大字典,但在理论上肯定不会更快。 - Mark Amery

0

尝试使用这个适用于Python 2.7/3.x的代码

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

0

函数对于列表类型的值是对称的;当执行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

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()构造函数接受元组列表。它也接受map的结果,因此我们可以跳过转换为列表的步骤。
  • 这个解决方案没有显式的for循环。它还避免使用列表推导式,对于那些不擅长数学的人来说,这是一个好消息 ;-)

我在谷歌搜索、其他答案或重复问题中都找不到这个解决方案,所以我自己创建了它。 - mit

0

即使在原始字典中存在非唯一值,此方法仍然有效。

def dict_invert(d):
    '''
    d: dict
    Returns an inverted dictionary 
    '''
    # Your code here
    inv_d = {}
    for k, v in d.items():
        if v not in inv_d.keys():
            inv_d[v] = [k]
        else:
            inv_d[v].append(k)
        inv_d[v].sort()
        print(f"{inv_d[v]} are the values")
        
    return inv_d

这个解决方案不起作用,我尝试过了,出现了一个TypeError错误:不可哈希类型:"list"。 - undefined
你能展示一下你正在使用的数据的例子吗? - undefined

0
根据使用情况,可能有一种使用枚举的方法。
import enum

class Reverse(enum.Enum):
    a = 1
    b = 2

你可以双向访问这些值:
Reverse.a       --> prints Reverse.a
Reverse(1)      --> prints Reverse.a

Reverse.a.value --> prints 1
Reverse.a.name  --> prints 'a'

如果开发者不知道'a',而是包含在一个变量my_var = 'a'中,那么my_dict[my_var]的等价物将是:
getattr(Reverse, my_var) --> prints Reverse.a

-1

我会在Python 2中这样做。

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

通过使用 dict.items(或在 Python 2 中使用 iteritems)同时迭代键值对比单独提取每个值更有效率。 - jpp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接