Python 合并多个字典或映射

合并多个字典或映射


ChainMap

假设有多个字典或者映射,需求是将这些字典或者映射,从逻辑上合并为一个单一的映射后执行其他操作,例如查找值或者检查某些键是否存在。

假如有如下两个字典:

>>> a = {'x': 1, 'z':3}
>>> b = {'y': 2, 'z': 4}

假设现在的需求是在两个字典中执行查询操作,先在字典 a 中查找,若查询无结果,再在 b 中查找。这里有个解决方案就是使用 collections 模块中提供的 ChainMap 类。示例如下:

>>> from collections import ChainMap
>>> c = ChainMap(a, b)
>>> c['x']  # 从 a 中输出
1
>>> c['y']  # 从 b 中输出
2
>>> c['z']  # 从 a 中输出
3

ChainMap 作用是将多个字典或者其他映射组合在一起,创建一个单独的可更新的视图。这里的意思是,原多个字典并非真的合并在一起,是 ChainMap 类在内部创建一个容纳这些字典列表,同时重新定义一些常见的字典操作来遍历这个列表。以下是使用 ChainMap 后的一部分字典操作:

>>> len(c)
3
>>> list(c.keys())
['z', 'y', 'x']
>>> list(c.values())
[3, 2, 1]

这里特别提及下,如果出现重复键,会返回第一次出现的映射值。因此,上面例子中, c['z'] 返回的值总是对应字典 a,而不是字典 b

同时,对于字典的更像或者删除操作也同样是影响列表中的第一个字典。示例如下:

>>> c['z'] = 10
>>> c['w'] = 60
>>> del c['x']
>>> a
{'z': 10, 'w': 60}
>>> del c['y']
Traceback (most recent call last):
...
KeyError: "Key not found in the first mapping: 'y'"

new_child() 和 parents


ChainMap 还有个 new_child 方法和 parents 属性。

下面是两者的一些使用方法:

>>> values = ChainMap()
>>> values['x'] = 1
>>> # 添加一个新的映射
... values = values.new_child()
>>> values['x'] = 2
>>> # 添加一个新的映射
... values = values.new_child()
>>> values['x'] = 3
>>> values
ChainMap({'x': 3}, {'x': 2}, {'x': 1})
>>> values['x']
3
>>> # 丢弃映射
... values = values.parents
>>> values['x']
2
>>> values = values.parents
>>> values['x']
1
>>> values
ChainMap({'x': 1})

从上面的例子中可以看到,new_child() 方法返回一个新的 ChainMap 类,包含一个新映射,后面跟随当前实例的全部映射。这个方法用于创建子上下文,不改变任何父映射的值。

parents 属性返回一个新的 ChainMap 包含所有的当前实例的映射,除了第一个。这样可以在搜索的时候跳过第一个映射。

作为 ChainMap 的替代,可以考虑 update() 方法将两个字典合并,示例如下:

>>> a = {'x': 1, 'z': 3}
>>> b = {'y': 2, 'z': 4}
>>> merged = dict(b)
>>> merged.update(a)
>>> merged['x']
1
>>> merged['y']
2
>>> merged['z']
3
>>>

update() 方法同样能够实现需求,但是,它需要新建一个完全不同的字典对象(或者破坏现有的字典结构),还有一点是,原字典所做的更像,不会反应到新的字典中。示例如下:

>>> a['x'] = 13
>>> merged['x']
1

对字典 a 中的 x 进行更改,合并后的字典并没有发生改变。

ChainMap 使用原来的字典,它自己不创建新的字典。所以不会出现上面的情况,示例如下:

>>> a = {'x': 1, 'z': 3}
>>> b = {'y': 2, 'z': 4}
>>> merged = ChainMap(a, b)
>>> merged['x']
1
>>> a['x'] = 13
>>> merged['x']  # 这里可以注意到用 ChainMap 合并的字典,值同样发生了改变
13

以上就是本篇的主要内容。


发布了52 篇原创文章 · 获赞 16 · 访问量 5731

猜你喜欢

转载自blog.csdn.net/weixin_45642918/article/details/103657452