Pythonで複数の辞書のキーに対する集合演算(共通、和、差、対称差)
Pythonで辞書(dict
型オブジェクト)のメソッドkeys()
とitems()
を使うと、キーkey
およびキーと値のタプル(key, value)
に対して集合演算が可能。
キーと値のタプルから辞書を生成できるので、例えば、複数の辞書に共通する要素(キーと値)からなる辞書を生成したりできる。
辞書オブジェクトのkeys()メソッドとitems()メソッド
辞書オブジェクトにはkeys()
メソッドとitems()
メソッドがある。
keys()
はキーkey
の、items()
はキーと値のタプル(key, value)
のビューを返す。
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 2, 'c': 4, 'd': 5}
print(d1.keys())
# dict_keys(['a', 'b', 'c'])
print(type(d1.keys()))
# <class 'dict_keys'>
print(d1.items())
# dict_items([('a', 1), ('b', 2), ('c', 3)])
print(type(d1.items()))
# <class 'dict_items'>
それぞれdict_keys
型、dict_items
型だが、set
型のような集合演算をサポートしている。
辞書オブジェクトには値value
のビューを返すvalues()
メソッドもあるが、値は重複する場合があるので集合演算はサポートされていない。
以下、keys()
メソッドとitems()
メソッドを利用した集合演算の例を示す。
複数の辞書に共通のキーを抽出(共通部分)
複数の辞書に共通しているキーはkeys()
メソッドと&
演算子で抽出できる。
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 2, 'c': 4, 'd': 5}
intersection_keys = d1.keys() & d2.keys()
print(intersection_keys)
# {'c', 'b'}
集合演算の結果はset
型。以降の例でも同じ。
print(type(intersection_keys))
# <class 'set'>
items()
メソッドの場合、キーと値が両方とも共通のものが抽出される。キーのみ、あるいは、値のみが共通のものは除外される。
intersection_items = d1.items() & d2.items()
print(intersection_items)
# {('b', 2)}
辞書オブジェクトのコンストラクタdict()
にタプル(key, value)
の集合(items()
メソッドの集合演算結果)を渡すと辞書を生成できる。
intersection_dict = dict(d1.items() & d2.items())
print(intersection_dict)
# {'b': 2}
print(type(intersection_dict))
# <class 'dict'>
複数の辞書に含まれるキーをすべて抽出(和集合)
複数の辞書に含まれるすべてのキー、つまり、複数の辞書のいずれかに少なくとも一つ含まれるキー(和集合)は|
演算子で抽出できる。
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 2, 'c': 4, 'd': 5}
union_keys = d1.keys() | d2.keys()
print(union_keys)
# {'d', 'c', 'a', 'b'}
items()
メソッドの場合は以下の通り。キーが共通でも値が異なる要素は別々に抽出される。
union_items = d1.items() | d2.items()
print(union_items)
# {('b', 2), ('a', 1), ('c', 4), ('d', 5), ('c', 3)}
この例のようにキーが共通で値が異なる要素があると、その集合から辞書を生成する場合にどちらか一方のみが残る。どちらの値が残るかは指定できない。
union_dict = dict(d1.items() | d2.items())
print(union_dict)
# {'b': 2, 'a': 1, 'c': 3, 'd': 5}
なお、Python 3.9以降、|
演算子で2つの辞書をマージできるようになった。この処理では、共通のキーがある場合は右側の辞書の値が残る。
- 関連記事: Pythonで辞書同士を結合(連結・マージ)
print(d1 | d2)
# {'a': 1, 'b': 2, 'c': 4, 'd': 5}
print(d2 | d1)
# {'b': 2, 'c': 3, 'd': 5, 'a': 1}
複数の辞書のいずれかにのみ含まれるキーを抽出(差集合、対称差集合)
複数の辞書のいずれか一方にのみ含まれるキー(対称差集合)は^
演算子で抽出できる。
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 2, 'c': 4, 'd': 5}
symmetric_difference_keys = d1.keys() ^ d2.keys()
print(symmetric_difference_keys)
# {'d', 'a'}
items()
メソッドの場合は以下の通り。|
演算子(和集合)と同様に、キーが共通でも値が異なる要素は別々に抽出される。
symmetric_difference_items = d1.items() ^ d2.items()
print(symmetric_difference_items)
# {('d', 5), ('a', 1), ('c', 3), ('c', 4)}
この例のようにキーが共通で値が異なる要素があると、その集合から辞書を生成する場合にどちらか一方のみが残る。どちらの値が残るかは指定できない。
symmetric_difference_dict = dict(d1.items() ^ d2.items())
print(symmetric_difference_dict)
# {'d': 5, 'a': 1, 'c': 4}
-
演算子で差集合を取得することもできる。
difference_keys = d1.keys() - d2.keys()
print(difference_keys)
# {'a'}
difference_items = d1.items() - d2.items()
print(difference_items)
# {('a', 1), ('c', 3)}
difference_dict = dict(d1.items() - d2.items())
print(difference_dict)
# {'a': 1, 'c': 3}