如何在Python中将2个字典变成1个?

问题描述 投票:0回答:6

我有两本词典:

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
6个回答
5
投票

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

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}

3
投票

一般来说,对字典求和应该这样完成:

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

如果您有重复的键,您想要对哪些值求和,下面的代码片段将完成这项工作:

#!/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}

2
投票

当您意识到所请求的功能是围绕 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"}

2
投票

对于那些可以导入模块的人:只需使用

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

1
投票

问题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)},因为key'apple'同时存在于fruit1和fruit2中。然后当迭代去添加'banana'时,在fruit1中找到了key,但在fruit2中找不到。

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


1
投票

您可以使用

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

© www.soinside.com 2019 - 2024. All rights reserved.