如果两个字典的键相等,则使用两个值执行操作并移动到新字典 (python)



我有两个字典,像这样:

d1 = {'red':10, 'blue':20, 'green':30, 'yellow':40}
d2 = {'red':1, 'blue':2, 'green':3}

我想遍历 d1 中的每个项目,看看键是否与 d2 中的键匹配。如果是这样,我想从 d2 键中减去 d1 键,并将新的键/值对移动到新字典中,结果:

d3 = {'red':9, 'blue':18, 'green':27, 'yellow':40}

我编写了以下脚本来执行此操作:

for x, y in d1.items():
    for a, b in d2.items():
        if x == a:
            d3[x] = (y-b)
        elif x not in d2.items():
            d3[x] = y

这有效,但是当我尝试在包含数千个项目的两个词典上使用它时,该功能永远不会完成。我想这太慢了。

你能推荐一个更好的方法来做到这一点吗?多谢。

是的,你把事情弄得太复杂了,只需使用字典理解

{k:v1-d2.get(k,0) for k,v1 in d1.items()}

这将生成:

>>> {k:v1-d2.get(k,0) for k,v1 in d1.items()}
{'red': 9, 'blue': 18, 'green': 27, 'yellow': 40}

代码的工作原理如下:字典推导将遍历d1items()k键并v1k关联的d1的值。

然后,对于每个这样的键值对,我们将v1-d2.get(k,0)与结果字典中的键k相关联。 d2.get(k,0)的目标是获取与k关联的值,如果键不在字典中,它将返回0

算法运行 - 给定字典查找可能发生在 O(1( 中(不能保证,但很有可能( - 在 O(n( 中,n 个元素的数量在d1,所以相当快。

您可以将字典理解与 if-else 语句一起使用:

d1 = {'red':10, 'blue':20, 'green':30, 'yellow':40}
d2 = {'red':1, 'blue':2, 'green':3}
new_dict = {a:b-d2[a] if a in d2 else b for a, b in d1.items()}

输出:

{'blue': 18, 'green': 27, 'red': 9, 'yellow': 40}

只是为了记录(因为我发现字典理解非常优雅(,你也可以使用集合。此任务的计数器(也非常整洁(:

In [1]: from collections import Counter
In [2]: d1 = {'red':10, 'blue':20, 'green':30, 'yellow':40}
   ...: d2 = {'red':1, 'blue':2, 'green':3}
   ...: 
In [3]: A = Counter(d1)
In [4]: B = Counter(d2)
In [5]: A - B
Out[5]: Counter({'blue': 18, 'green': 27, 'red': 9, 'yellow': 40})

正如@WillemVanOnsem的评论所指出的,

"如果 D2 中的值高于 D1 中的相应值,我们将 没有获得负数,但键将消失:计数器 通常假设计数是自然数"。

但是,还有另一种解决方案通过使用其substract()方法(仅在python 3.2中引入(依赖于Counter,但它将修改您的Counter对象之一(因为它的行为dict.update()

In [26]: A = Counter({'red':10, 'blue':20, 'green':30, 'yellow':40})
    ...: B = Counter({'red':1, 'blue':30, 'green':3})
    ...: 
In [27]: A - B # The 'blue' key disappear 
Out[27]: Counter({'green': 27, 'red': 9, 'yellow': 40})
In [28]: A.subtract(B) # It handles negative values ...
In [29]: A # ...but modify the counter A
Out[29]: Counter({'blue': -10, 'green': 27, 'red': 9, 'yellow': 40})

collections.Counter的主要目的是计算/存储可散列对象的出现(因此假设计数是自然数(,但它基本上是字典的一个子类,它提供了几种操作来组合它们之间的Counter对象(加法,减法,联合和交集(。

最新更新