在 Python 中反转字典

Posted

技术标签:

【中文标题】在 Python 中反转字典【英文标题】:inverting a dictionary in Python 【发布时间】:2021-08-21 20:29:33 【问题描述】:

这是一个反转字典的代码,但为了理解 定义的函数 invert_dict(dic) 中每个代码元素的作用,我遇到了一些麻烦,如果有人把它分解给我,并向我解释每个元素的使命。 谢谢。

animals = 'Lion':["meet", 1.2 ,'yellow'],'Cat':["milk", 0.3,'white'],'dog':["Dog", 1,'black']

def invert_dict(dic):
    return v: d.setdefault(v, []).append(k) or d[v] for d in (,) for k in dic for v in dic[k]

print(invert_dict(animals))

输出:

'meet': ['Lion'], 1.2: ['Lion'], 'yellow': ['Lion'], 'milk': ['Cat'], 0.3: ['Cat'], 'white': ['Cat'], 'Dog': ['dog'], 1: ['dog'], 'black': ['dog']

【问题讨论】:

【参考方案1】:

听起来像是 defaultdict 的经典用法

animals = 'Lion':["meet", 1.2 ,'yellow'],'Cat':["milk", 0.3,'white'],'dog':["Dog", 1,'black']

from collections import defaultdict
def invert_dict(d):
    ret = defaultdict(list)
    d = [(v,k) for k, lst in d.items() for v in lst]
    for k,v in d.items():
        ret[k].append(v)
    return dict(ret)

【讨论】:

【参考方案2】:
v: d.setdefault(v, []).append(k) or d[v] for d in (,) for k in dic for v in dic[k]

让我们从右边分解一下

for k in dic for v in dic[k]

使用带有值的字典作为列表 k: [v1, v2] ,并提取对应的键为kv = [v1, v2]中的值列表

v: d.setdefault(v, []).append(k) or d[v] for d in (,)

for v in dic[k] 循环每个键的值,即[v1, v2],并使用defaultdict 来标识结果字典中已经存在的值,如果存在,它将原始字典中的键附加到新字典中产生的倒排字典。如果没有,它会分配密钥。

对于一个样本 k: [v1, v2, v3], z: [v1] ,每次运行后,倒排字典的状态如下:


 v1 : [k] 
 v1 : [k], v2 : [k] 
 v1 : [k], v2 : [k], v3: [k] 
 v1 : [k, z], v2 : [k], v3: [k]   # because v1 already exists, z is appended

这相当于:

from collections import defaultdict

def invert_dict_exploded(dic):
    d = defaultdict(list)
    for key in dic:
        for value in dic[key]:
            d[value].append(key)
    return dict(d)

【讨论】:

【参考方案3】:

我们需要按顺序,从外到内:

大括号和冒号表示法 For 循环 附加

大括号

大括号在 Python 中用于创建字典或集合。在这种情况下,它们用于创建字典,因为我们有 key: value 符号。在本次讨论中,我们称其为“返回的字典”。

For 循环

这些 for 循环相当于:

for d in (,):
    for k in dic:
        for v in dic.values():
            ...

这是一种速记符号,可以方便地快速创建集合。当它没有被滥用时,它通常是非常可读的。

for d in (,) 仅用于声明一个字典,该字典将在迭代键和值时坐在那里(因为正如我们在上面看到的,它位于最外层循环中)。字典名为d

附加

对于每个键/值对,我们使用冒号表示法在返回的字典中创建一个新键,其中键实际上是输入值之一,然后我们做两件事:

    在我们的 d 字典中添加一个项目,该字典始终是一个列表 将列表分配给给定的键

如果在字典中没有找到键 vk.setdefault(v, []) 位将设置默认值 [],然后将返回该列表(新创建的空列表或在该键处找到的列表),这然后由.append(k) 位使用,将键作为值附加到该列表中。这会处理输入列表中具有相同值的项目的情况,并将该值的所有键收集在一起,例如:

animals = 'Lion':["meet", 1.2 ,'yellow'],'Cat':["milk", 0.3,'black'],'dog':["Dog", 1,'black']

您可以在其中看到包含“黑色”项目的多个列表,并将输出以下内容:

'meet': ['Lion'], 1.2: ['Lion'], 'yellow': ['Lion'], 'milk': ['Cat'], 0.3: ['Cat'], 'black': ['Cat', 'dog'], 'Dog': ['dog'], 1: ['dog']

请注意,“Cat”和“dog”键都被添加到结果中的“black”列表中。

最后,部分。 list.append() 函数总是返回 None,因为每个没有显式返回的函数都会在 Python 中自动返回 None

or 运算符用于短路表达式。它被写成A or B 并且被读作“如果 A 的计算结果为真值,则表达式的计算结果为 A;如果 A 的计算结果为假值,则表达式的计算结果为 B”。 None 总是以布尔形式计算为 false,因此表达式 d.setdefault(v, []).append(k) or d[v] 总是计算为 d[v],但仅在执行 setdefault()append() 之后。

v: d.setdefault(v, []).append(k) or d[v] 因此可以读作:

在我们的返回的字典中创建一个键v;如果v不是d的键,则设置d[v] = [];将k的值附加到d[v],并将d[v]设置为v的值。

【讨论】:

以上是关于在 Python 中反转字典的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中反转字典并从重复的键值中创建一个列表

python反转字典键值

python——反转字典的两种方法(字典的key和value对换)

python 中如何将一个字符反转

如何反转多维数组中的重复值

在Django模板中渲染有序反转字典值