【问题标题】:How to Turn 2 Dictionaries into 1 in Python?如何在 Python 中将 2 个字典变成 1 个?
【发布时间】:2022-08-21 11:49:56
【问题描述】:

我有两本词典:

fruit1 = {\'apple\': 3, \'banana\': 1, \'cherry\': 1}
fruit2 = {\'apple\': 42, \'peach\': 1}

我想要的最终结果是:

inv3 = {\'apple\': 45, \'banana\': 1, \'cherry\': 1, \'peach\': 1}

到目前为止,我已经尝试过这个示例代码,因为这个输出看起来与我想要的几乎相似,除了它没有按照我想要的方式打印出来而是关闭:

d1 = {\'apple\': 3, \'orange\': 1,} 
d2 = {\'apple\': 42, \'orange\': 1}

ds = [d1, d2]
d = {}

for k in d1.keys():
    d[k] = tuple(d[k] for d in ds)
print(ds)

输出将是这样的:

[{\'apple\': 3, \'orange\': 1}, {\'apple\': 42, \'orange\': 1}]

当我尝试使用示例代码输入我的 2 个字典时:

fruit1 = {\'apple\': 3, \'banana\': 1, \'cherry\': 1}
fruit2 = {\'apple\': 42, \'peach\': 1}      

fruit3 = [fruit1, fruit2]
d = {}
            
for k in fruit1.keys():
d[k] = tuple(d[k] for d in fruit3)
print(fruit3)

我收到此错误消息:

Traceback (most recent call last):
  line 8, in <module>
    d[k] = tuple(d[k] for d in ds)
  line 8, in <genexpr>
    d[k] = tuple(d[k] for d in ds)
KeyError: \'banana\'

我的问题是:

  1. 如何在不导入任何模块的情况下获得我想要的输出?我只在第 5 章:自动化无聊的东西中的字典和数据结构
  2. 为什么会出现 KeyError:\'banana\'?

    谢谢!

标签: python list dictionary key-value


【解决方案1】:

有很多方法可以实现这一目标。这是一个:

fruit1 = {'apple': 3, 'banana': 1, 'cherry': 1}
fruit2 = {'apple': 42, 'peach': 1}

inv3 = {}

for d in fruit1, fruit2:
    for k, v in d.items():
        inv3[k] = inv3.get(k, 0) + v

print(inv3)

输出:

{'apple': 45, 'banana': 1, 'cherry': 1, 'peach': 1}

【讨论】:

  • 这可能是提议的解决方案中最优雅的解决方案,因为它依赖于默认值,以防键不在字典中。
  • 所以我现在明白我被困在嵌套的 for 循环中了。现在更清楚了。谢谢,@lancelot du Lac。
【解决方案2】:

一般来说,对字典求和应该是这样的:

>>> d1 = {'a': 5}
>>> d2 = {'b': 6}
>>> d3 = { **d1, **d2 }
>>> d3
{'a': 5, 'b': 6}

如果你有重复的键,你想对哪些值求和,下面的 sn-p 将完成这项工作:

#!/usr/bin/env python

def sum_dicts(*dicts: dict) -> dict:
    out = {}
    for dictionary in dicts:
        for key, value in dictionary.items():
            if key not in out:
                out[key] = value
                continue
            out[key] += value
    return out


if __name__ == '__main__':
    fruit1 = {'apple': 3, 'banana': 1, 'cherry': 1}
    fruit2 = {'apple': 42, 'peach': 1}
    print(sum_dicts(fruit1, fruit2))

输出:

{'apple': 45, 'banana': 1, 'cherry': 1, 'peach': 1}

【讨论】:

    【解决方案3】:

    当您意识到请求的功能是围绕 Monoid(半群)的结构时,您可以使用一些构建块直接表达此行为:为字典集合实现 __getitem__keys 方法,您就在那里!

    
    class SummedDict:
        """Represents memberwise summation of dicts."""
        
        def __init__(self, *dicts):
            self.dicts = dicts
    
        def get(self, key, default=0):
            return sum(d.get(key, default) for d in self.dicts)
    
        def __getitem__(self, key):
            return self.get(key, 0)
    
        def __add__(self, other: MutableMapping) -> "SummedDict":
            return SummedDict(self, other)
    
        def keys(self):
            return reduce(lambda ks, d: ks.union(d.keys()), self.dicts, set())
    
    
    def test_dicts_can_be_summed():
        d1 = dict(a=1, b=2, c=3)
        d2 = dict(a=1, c=3)
        m = SummedDict(d1, d2)
        assert m["a"] == 2
        assert m["b"] == 2
        assert m["c"] == 6
        assert m.keys() == {"a", "b", "c"}
    

    【讨论】:

      【解决方案4】:

      对于那些能够导入模块:只需使用collections.Counter

      from collections import Counter
      
      all_the_fruits = Counter()
      all_the_fruits.update(fruit1)
      all_the_fruits.update(fruit2)
      print(all_the_fruits)
      
      Counter({'apple': 45, 'banana': 1, 'cherry': 1, 'peach': 1})
      

      【讨论】:

        【解决方案5】:

        问题 1. 如何在不导入任何模块的情况下获得我想要的输出?

        我的建议是从头开始创建字典。让我从上面的示例代码中扩展:

        fruit1 = {'apple': 3, 'banana': 1, 'cherry': 1}
        fruit2 = {'apple': 42, 'peach': 1}
        d = {}
        for fruit in [fruit1, fruit2]:
            for k in fruit.keys():
                if k in d.keys():
                    d[k] += fruit[k]
                else:
                    d[k] = fruit[k]
        print(d)
        

        输出:

        {'apple': 6, 'banana': 1, 'cherry': 1, 'peach': 1}
        

        问题 2. 为什么会出现 KeyError: 'banana'?

        你得到KeyError: 'banana' 的原因是找不到密钥。

        形成的第一个元组是 {'apple': (3, 42)} 因为键 'apple' 存在于fruit1 和fruit2 中。然后当迭代去添加'banana'时,在fruit1中找到了key,但在fruit2中找不到。

        因此,在我上面的代码中,如果密钥存在,则添加数字。如果密钥不存在,则创建它。

        【讨论】:

          【解决方案6】:

          您可以使用 try 块来强制添加:

          for k, v in fruit1.items():
              try:
                  fruit2[k] += v
              except KeyError:
                  fruit2[k] = v
          
          >>> fruit2
          {'apple': 45, 'peach': 1, 'banana': 1, 'cherry': 1}
          

          这基于fruit2

          【讨论】:

            猜你喜欢
            • 2010-12-05
            • 1970-01-01
            • 2022-06-10
            • 1970-01-01
            • 2017-01-09
            • 1970-01-01
            • 2017-05-04
            • 2016-05-13
            • 1970-01-01
            相关资源
            最近更新 更多