我有两个字典:
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}]
当我尝试使用示例代码输入我的两个字典时:
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'
我的问题是:
- 我如何得到我没有导入任何模块的输出?我只看到第5章:字典和数据结构自动化无聊的东西 为什么会出现KeyError: 'banana' ?
谢谢!
有很多方法可以做到这一点。这里有一个:
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}
一般来说,对字典求和应该这样做:
>>> 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}
当你意识到所要求的功能是围绕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"}
导入模块:只使用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。如何在不导入任何模块的情况下获得预期的输出?
我的建议是从头创建字典。让我从上面的示例代码扩展:
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中找到了键,但在fruit2中找不到键。
因此,在我上面的代码中,如果键存在,则添加数字。如果密钥不存在,创建一个
您可以使用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