2つの辞書をマージする

2つの辞書をマージする

2つの辞書をマージする方法はいくつかありますが、それぞれ特徴がありますので用途にあったやり方を使ってみましょう。

updateメソッド

dict型にはupdateという辞書をマージするメソッドがあります。

dict1 = {"a":1, "b":2}
dict2 = {"c":3, "d":4}

dict1.update(dict2) # dict1にdict2をマージする
print(dict1)
# {'a': 1, 'b': 2, 'c': 3, 'd': 4}

引数にマージしたい辞書を指定するだけです。また、キーに重複がある場合は引数で指定した辞書の値が優先されます。元のdict1自体が変更されている点に注意してください。

dict関数

前述の通り、updateメソッドはマージしたdict1に対して破壊的に作用します。もし新たに辞書を作成したい場合は組み込み関数のdict()で新たに生成すると良いでしょう。第1引数に辞書を、第2引数はキーワード引数で指定します。

dict1 = {"a":1, "b":2}
dict2 = {"c":3, "d":4}
dict3 = dict(dict1, **dict2) # 第2引数はキーワード引数とする
print(dict3)
# {'b': 2, 'a': 1, 'd': 4, 'c': 3}

キーに重複がある場合はキーワード引数で指定したほうに上書きされます。

https://docs.python.jp/3/library/stdtypes.html#dict
キーワード引数が与えられた場合、キーワード引数とその値が位置引数から作られた辞書に追加されます。既に存在しているキーが追加された場合、キーワード引数の値は位置引数の値を置き換えます。

collections.ChainMap

標準ライブラリのcollectionsモジュールにはChainMapという型があります。元のオブジェクトを破壊せず、なおかつ新たなインスタンスを生成しないでマージしたビューのみ提供してくれます。

複数の辞書をマージする場合、新たな辞書を生成してupdate() を繰り返すよりも高速です。パフォーマンスを気にする場合に使用を検討してください。

from collections import ChainMap

dict1 = {"a":1, "b":2}
dict2 = {"c":3, "d":4}
chain_map = ChainMap(dict1, dict2)
print(chain_map['a'])
# 1

ただし、参照がコピーされているだけなので、chainmapを更新すると元のインスタンスも更新されるという点に注意してください。

# 上からの続き
chain_map["a"] = 100
print(dict1)
# {'a': 100, 'b': 2}

chain_mapを更新すると、元の辞書も更新されたことが確認できます。