Python の集合演算(和集合・積集合・差集合・対称差)
集合演算は、複数の集合を組み合わせて新しい集合を得る操作だ。Python では演算子とメソッドの両方で実行できる。
和集合(Union)
和集合は、どちらかの集合に含まれるすべての要素を集めたものだ。| 演算子または union() メソッドで取得する。
a = {1, 2, 3}
b = {3, 4, 5}
# 演算子
print(a | b) # {1, 2, 3, 4, 5}
# メソッド
print(a.union(b)) # {1, 2, 3, 4, 5}
両方に含まれる 3 は、結果には 1 回だけ現れる。これが集合の重複排除の性質だ。
積集合(Intersection)
積集合は、両方の集合に共通して含まれる要素だけを集めたものだ。& 演算子または intersection() メソッドを使う。
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# 演算子
print(a & b) # {3, 4}
# メソッド
print(a.intersection(b)) # {3, 4}
共通要素がない場合は空集合が返る。
a = {1, 2}
b = {3, 4}
print(a & b) # set()
差集合(Difference)
差集合は、一方の集合から他方の要素を取り除いたものだ。- 演算子または difference() メソッドで得られる。
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# a から b の要素を除く
print(a - b) # {1, 2}
# b から a の要素を除く
print(b - a) # {5, 6}
# メソッド
print(a.difference(b)) # {1, 2}
差集合は順序が重要だ。a - b と b - a は異なる結果になる。
a に含まれるが b には含まれない要素
b に含まれるが a には含まれない要素
対称差(Symmetric Difference)
対称差は、どちらか一方にのみ含まれる要素を集めたものだ。両方に含まれる要素は除外される。^ 演算子または symmetric_difference() メソッドを使う。
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# 演算子
print(a ^ b) # {1, 2, 5, 6}
# メソッド
print(a.symmetric_difference(b)) # {1, 2, 5, 6}
対称差は和集合から積集合を引いたものと同じだ。
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a ^ b) # {1, 2, 5, 6}
print((a | b) - (a & b)) # {1, 2, 5, 6}
演算子とメソッドの違い
演算子は集合同士でしか使えないが、メソッドは任意のイテラブルを引数に取れる。
a = {1, 2, 3}
# メソッドはリストを直接渡せる
print(a.union([3, 4, 5])) # {1, 2, 3, 4, 5}
print(a.intersection([2, 3, 4])) # {2, 3}
# 演算子はエラー
# print(a | [3, 4, 5]) # TypeError
複数のイテラブルを一度に処理できるのもメソッドの利点だ。
a = {1, 2}
print(a.union([3, 4], {5, 6}, (7, 8))) # {1, 2, 3, 4, 5, 6, 7, 8}
破壊的な集合演算
元の集合を直接変更する破壊的メソッドも用意されている。
| 非破壊的 | 破壊的 |
|---|---|
| union() | update() |
| intersection() | intersection_update() |
| difference() | difference_update() |
| symmetric_difference() | symmetric_difference_update() |
破壊的メソッドは戻り値が None で、元の集合を直接変更する。
a = {1, 2, 3}
a.update({4, 5})
print(a) # {1, 2, 3, 4, 5}
b = {1, 2, 3, 4}
b.intersection_update({2, 3, 5})
print(b) # {2, 3}
|=、&=、-=、^= といった複合代入演算子も使える。
a = {1, 2, 3}
a |= {4, 5}
print(a) # {1, 2, 3, 4, 5}
b = {1, 2, 3, 4}
b &= {2, 3, 5}
print(b) # {2, 3}
複数集合の演算
3 つ以上の集合に対しても演算できる。
a = {1, 2, 3}
b = {2, 3, 4}
c = {3, 4, 5}
# 3 つの和集合
print(a | b | c) # {1, 2, 3, 4, 5}
# 3 つの積集合
print(a & b & c) # {3}
メソッドを使えば可変長引数で渡せる。
sets = [{1, 2}, {2, 3}, {2, 4}]
result = set.intersection(*sets)
print(result) # {2}
set.intersection() のようにクラスメソッドとして呼び出すと、すべての集合の共通要素を求められる。