反转/倒置字典映射

2024-11-26 08:36:00
admin
原创
189
摘要:问题描述:给定一个这样的字典:my_map = {'a': 1, 'b': 2} 如何反转此图以获得:inv_map = {1: 'a', 2: 'b'} 解决方案 1:Python 3+:inv_map = {v: k for k, v in my_map.items()} Python 2:inv_map...

问题描述:

给定一个这样的字典:

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

如何反转此图以获得:

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

解决方案 1:

Python 3+:

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

Python 2:

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

解决方案 2:

假设字典中的值是唯一的:

Python 3:

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

Python 2:

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

解决方案 3:

如果中的值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]

解决方案 4:

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

def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))

解决方案 5:

尝试一下:

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 的字典推导

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

解决方案 6:

另一种更实用的方法:

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

解决方案 7:

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

解决方案 8:

这扩展了罗伯特的回答,适用于字典中的值不唯一的情况。

class ReversibleDict(dict):
    # Ref: https://stackoverflow.com/a/13057382/
    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.items():
            revdict.setdefault(v, []).append(k)
        return revdict

该实现的局限性在于您无法使用reversed两次并取回原始值。它本身并不对称。它已使用 Python 2.6 进行了测试。下面是我用来打印结果字典的用例。

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

解决方案 9:

例如,您有以下词典:

my_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 my_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 my_dict.items()}

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

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

my_dict = {value: key for key in inverted_dict for value in my_map[key]}

解决方案 10:

字典值是集合的情况。例如:

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

解决方案 11:

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

解决办法是:

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

解决方案 12:

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

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

解决方案 13:

我发现这个版本比具有 10,000 个键的字典的接受版本快 10% 以上。

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

new_d = dict(zip(d.values(), d.keys()))

解决方案 14:

除了上面建议的其他函数之外,如果您喜欢 lambda:

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

或者,你也可以这样做:

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

解决方案 15:

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

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 中的值,并且您的逆字典将始终有效——如果您只是反转整个字典一次,情况就不一样了。

解决方案 16:

如果值不唯一,并且你有点太过严格:

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 反转/反转映射,因为它循环items()多次。

解决方案 17:

这可以处理非唯一值并保留大部分唯一情况的外观。

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

对于 Python 3.x,请替换itervaluesvalues

解决方案 18:

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

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

解决方案 19:

这是另一种方法。

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

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

解决方案 20:

dict([(value, key) for key, value in d.items()])

解决方案 21:

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

解决方案 22:

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

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

解决方案 23:

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

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

解决方案 24:

尝试使用 Python 2.7/3.x

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

解决方案 25:

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

解决方案 26:

适用于当前 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对数学不好的人使用 ;-)

解决方案 27:

谈到得票率很高的答案如果 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)]

解决方案 28:

即使原始字典中的值不唯一,这种方法仍然有效。

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

解决方案 29:

根据用例,可能有一种使用枚举的方法:

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

解决方案 30:

我会在 python 2 中这样做。

inv_map = {my_map[x] : x for x in my_map}
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1572  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   0  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   0  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   0  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用