Pythonで2つの辞書を持っていて、それを結合したいことはよくあります。
この記事では、Pythonで2つの辞書をマージする様々な方法を見ていきます。
いくつかの解決策はすべてのPythonのバージョンで利用できるわけではありませんので、特定のリリースのマージ方法も検討します。
辞書をマージするとき、2つの辞書が同じキーを持つ場合に何が起こるかを考慮する必要があります。
まず、マージの際に起こるべきことを定義しましょう。
Pythonで辞書をマージする
マージは通常、dict_a <- dict_b
のように右から左へと行われます。
両方の辞書に共通のキーホルダーがある場合、2番目の辞書の値が1番目の辞書の値を上書きします。
これは、以下の図に示すように、辞書Bの構成要素がAにマージされ、辞書Bの緑色のスーツがオレンジ色のスーツの代わりをすることで示される。
この記事では、以下の辞書を使用する。
- 値を持つ辞書
>>> a = {1:'peanut', 2:'butter', 3:'jelly', 4:'time'}
>>> b = {1:'fish', 2:'chips'}
- ネストされた値を持つ辞書。
>>> c = {1: ['peanut','butter','jelly','time'], 2:['fish','chips']}
>>> d = {1: ['fish','chips'], 2:['peanut','butter','jelly','time']}
Python 3.9 以降
Python バージョン 3.9 以降では、マージ演算子 (|
で表される) を使用して 2 つの辞書を結合することができます。
>>> x = a | b
>>> print(x)
{1: 'fish', 2: 'chips', 3: 'jelly', 4: 'time'}
辞書のマージ演算子は、ネストされた辞書の場所でも使用することができます。
ここでは、マッチしたキーの値の完全な上書きが行われる。
>>> y = c | d
>>> print(y)
{1: ['fish', 'chips'], 2: ['peanut', 'butter', 'jelly', 'time']}
Python 3 以上
Python 3 以前のバージョンでは、残念ながらマージ演算子を使用することができません。
代わりに、以下のように **
ダブルアスタリスクを使用して、両方の辞書を別の辞書の中に展開することでマージすることができます。
>>> x = {**a, **b}
>>> print(x)
{1: 'fish', 2: 'chips', 3: 'jelly', 4: 'time'}
同じことが、リストの値がネストされた辞書にも当てはまります。
重なっているキーの値は以下のように上書きされる。
>>> y = {**c, **d}
>>> print(y)
{1: ['fish', 'chips'], 2: ['peanut', 'butter', 'jelly', 'time']}
Python 2 以上
Pythonのレガシーバージョンでは、上記のスニペットは動作しません。
代わりに、辞書のアイテム、つまり両方の変数の dict_items
を組み合わせることで、マージを容易にすることができます。
また、 copy()
と update()
の辞書メソッドを使用することもできます。
最後に、辞書の項目をループして、 extend()
メソッドを使用して別の辞書に追加することができます。
items()を使用する
まず、items()
と組み合わせることから始めましょう。
>>> x = dict(a.items() + b.items())
>>> print(x)
{1: 'fish', 2: 'chips', 3: 'jelly', 4: 'time'}
上記のシンタックスは、単純な値に対して有効です。
リストの値を含むネストされた辞書の場合、 items()
コールを list()
にキャストしてから結合する必要があります。
>>> y = dict(list(c.items()) + list(d.items()))
>>> print(y)
{1: ['fish', 'chips'], 2: ['peanut', 'butter', 'jelly', 'time']}
この解決策は、キーが数値であるため、元のキーが保存され、うまく機能します。
異なる型のキーの場合は、次のようなオプションが望ましいでしょう。
辞書の使用 update()
マージを行うもうひとつの方法は、以下のように一方の辞書をコピーして、もう一方の辞書で更新することです。
>>> x = a.copy()
>>> x.update(b)
>>> print (x)
{1: 'fish', 2: 'chips', 3: 'jelly', 4: 'time'}
すべての Python バージョンでリストの値を追加する
これまでの節で、マージされた辞書のネストされた値を上書きしてきました。
ネストされた値を上書きするのではなく、追加する必要がある場合があります。
これは、以下のように extend()
メソッドを用いて行うことができます。
>>> for k, v in d.items():
... if k in c:
... c[k].extend(v)
... else:
... c[k] = v
>>>
>>> print(c)
{1: ['peanut', 'butter', 'jelly', 'time', 'fish', 'chips'], 2: ['fish', 'chips', 'peanut', 'butter', 'jelly']}
結論
この記事では、辞書のマージの仕組みと、異なるバージョンのPythonで2つの辞書をマージする方法について学びました。
辞書のマージは、複数のJSONファイルの読み込み、オブジェクトのマップの構築、コンテンツのインデックスの構築などの場面で非常に便利です。