【Python入門・応用】09.集合|重複した要素を削除できる「集合」の扱い方と特徴を学ぼう(初心者にもわかりやすく解説)

こんにちは。キノコードです。
この動画では、Pythonの集合について説明します。
説明する内容はこちらです。
はじめに、集合とは何かについて説明をします。
次に、集合の作り方、集合の扱い方を学びましょう。
また、集合に用意されているメソッドについても説明します。
集合の特徴を学習し、Pythonの知識を広げてみてください。

Python学習サービスの「キノクエスト」では、この動画で説明した内容の問題を解くことができます。
Pythonの基礎固めをして、プログラミングスキルを磨いてみませんか?
プログラミングで何がしたいかという目的別にカリキュラムがあります。
目的に合わせて必要な知識だけを学習することができます。
詳しくは概要欄に記載のURLからご確認ください。
月額1,990円のサブスクです。ご登録をお待ちしております!

それではレッスンスタートです。

集合とは

集合とは、大きく言うと、ものの集まりのことです。ある条件を満たすもの全体の集まりのことです。
集合はリストやタプルなどと異なり、一つ一つの要素に順番はありません。
また、要素の重複に意味はなく、同じ要素が一つでも二つでも同じ集合になります。
Pythonでは、集合の中に同じ要素が複数個あると、一つ残してその他は削除されます。
そのため、重複した要素を削除したいときなどに集合を使用します。

集合の作り方

それでは、実際にPythonで集合を作成してみましょう。
集合は辞書と同じように要素を波括弧で囲みます。
ただし、辞書と異なり、keyとvalueの組み合わせはありません。
それでは、このような0,1,2,3をランダムに複数個並べたデータの集合を考えてみましょう。

s = {0, 2, 1, 1, 2, 3, 1}

print(s)

波括弧の中に要素をカンマで区切って定義し、変数sに代入します。
print関数でsを表示してみましょう。
実行します。
集合が表示されました。
集合には要素の順番はないので、自動的に並び替えられます。
更に、要素の重複に意味はないので、重複した要素は一つだけ残り、その他は削除されます。

type関数でデータ型を確認してみましょう。

s = {0, 2, 1, 1, 2, 3, 1}

print(type(s))

実行します。
集合を意味する、setが表示されました。

また、異なるデータ型の要素を1つの集合として作成することもできます。

s = {123, 1.23, (1, 2, 3), 123, 1.23}

print(s)

このような、int型、float型、tuple型のデータを要素とした集合を作成してみましょう。
実行します。
集合が表示されました。
先ほどと同様に、重複した要素がなくなり、int型、float型、tuple型が含まれた集合となりました。

次に、tuple型の要素をlist型に変更して集合を作成してみましょう。

s = {123, 1.23, [1, 2, 3], 123, 1.23}

print(s)

実行します。
エラーが発生しました。
このように、集合を作成する場合、要素にリストや辞書のように更新ができるミュータブルなオブジェクトを含むことができません。

次に、set関数を使用して集合を作成してみましょう。
set関数の引数には、集合に変換したいオブジェクトを指定します。
リストを指定して、集合を作成してみましょう。

a = [0, 2, 1, 1, 2, 3, 1]
s = set(a)

print(s)

まず、リストのデータを変数aに代入します。
そして、set関数の引数にaを指定し、変数sに代入します。
print関数でsを表示してみましょう。
実行します。
リストから集合を作成できました。
波括弧で作成した集合と同様に、重複した要素がなくなり、自動的に並び替えられていることがわかります。

空集合の作り方

次に、要素を持たない空集合の作り方を説明します。
空集合はset関数を使用して作成します。
要素を持たない波括弧で定義すると、辞書とみなされてしまいます。
確認してみましょう。

s1 = set()
s2 = {}

print(type(s1))
print(type(s2))

引数無しのset関数を変数s1に代入し、要素を持たない波括弧を変数s2に代入します。
type関数でそれぞれのデータ型を確認してみます。
実行します。
s1のデータ型は集合を表すsetであり、s2のデータ型は辞書を表すdictであることがわかります。

要素を追加する方法

次に、集合に要素を追加する方法を説明します。

s = {0, 1, 2}
s.add(3)

print(s)

addメソッドを使用すると、集合に要素を追加できます。
引数に追加したい要素を指定します。
実行します。
集合に3を追加できました。

要素を削除する方法

続いて、集合から要素を削除する方法を説明します。

s = {0, 1, 2}
s.remove(1)

print(s)

removeメソッドを使用すると、集合から要素を削除できます。
引数に削除したい要素を指定します。
実行します。
集合から1を削除できました。

また、clearメソッドを使用すると、集合から全ての要素を削除できます。

s = {0, 1, 2}
s.clear()

print(s)

実行します。
集合から全ての要素を削除できました。

要素の変更ができない集合の作り方

今まで説明した、波括弧やset関数を使用した集合は、要素の追加や削除ができました。
frozenset関数を使用すると、要素の追加や削除ができない集合を作成できます。
集合の作成方法はset関数と同じです。

a = [0, 2, 1, 1, 2, 3, 1]
s = frozenset(a)

print(s)

まず、リストのデータを変数aに代入します。
そして、frozenset関数の引数にaを指定し、変数sに代入します。
print関数でsを表示してみましょう。
実行します。
frozensetと書かれた集合を作成できました。

この集合にaddメソッドを使用して、要素を追加してみましょう。

a = [0, 2, 1, 1, 2, 3, 1]
s = frozenset(a)
s.add(4)

print(s)

実行します。
エラーが発生しました。

次はclearメソッドを使用して、要素を削除してみましょう。

a = [0, 2, 1, 1, 2, 3, 1]
s = frozenset(a)
s.clear()

print(s)

実行します。
再びエラーが発生しました。
このように、frozenset関数で作成した集合は、要素の追加や削除ができません。

和集合

次に、和集合の作り方を説明します。
和集合とは、全ての集合のうち、少なくともどれか1つに含まれる要素の集合のことです。
|(バーティカルライン)やunionメソッドを使用すると、和集合を作成できます。

s1 = {0, 1, 2}
s2 = {1, 2, 3}

s3 = s1 | s2
print(s3)

s4 = s1.union(s2)
print(s4)

このような2つの集合s1,s2の和集合を作成してみましょう。
|(バーティカルライン)を使用する場合は、2つの集合の間に|(バーティカルライン)を記述します。
unionメソッドを使用する場合は、片方の集合のunionメソッドを記述し、引数にもう一方の集合を指定します。
実行します。
和集合を作成できました。
どちらも同じ結果になっていることが確認できます。

集合の演算

次に、集合の演算について説明します。
集合の演算には、和集合、積集合、差集合、対象差集合があります。
2つの集合で考えてみましょう。
和集合は、2つの集合の少なくともどちらか1つに含まれる要素の集合です。
積集合は、2つの集合のどちらにも含まれる要素の集合です。
差集合は、集合Aに含まれ、集合Bには含まれない要素の集合です。
対象差集合は、2つの集合のどちらかにだけ含まれる要素の集合です。
順番に見ていきましょう。

積集合

次に、積集合の作り方を説明します。
積集合とは、全て集合に含まれる要素の集合のことです。
&(アンパサンド)やintersectionメソッドを使用すると、積集合を作成できます。

s1 = {0, 1, 2}
s2 = {1, 2, 3}
s3 = {2, 3, 4}

s4 = s1 & s2 & s3
print(s4)

s5 = s1.intersection(s2, s3)
print(s5)

今度は、このような3つの集合s1,s2,s3の積集合を作成してみましょう。
&(アンパサンド)を使用する場合は、それぞれの集合の間に&(アンパサンド)を記述します。
intersectionメソッドを使用する場合は、1つの集合のintersectionメソッドを記述し、引数に残りの集合を指定します。
実行します。
積集合を作成できました。
どちらも同じ結果になっていることが確認できます。

差集合

次に、差集合の作り方を説明します。
差集合とは、集合Aには含まれるが、集合Bには含まれない要素の集合のことです。
-(マイナス)やdifferenceメソッドを使用すると、差集合を作成できます。

s1 = {0, 1, 2}
s2 = {1, 2, 3}

s3 = s1 - s2
print(s3)

s4 = s1.difference(s2)
print(s4)

このような2つの集合s1,s2の差集合を作成してみましょう。
-(マイナス)を使用する場合は、2つの集合の間に-(マイナス)を記述します。
この時、含まれる集合を最初に記述し、含まれない集合を後に記述します。
differenceメソッドを使用する場合は、含まれる集合のdifferenceメソッドを記述し、引数に含まれない集合を指定します。
実行します。
差集合を作成できました。
どちらも同じ結果になっていることが確認できます。

対称差集合

次に、対称差集合の作り方を説明します。
集合が2つの場合について説明します。
対称差集合とは、2つの集合のうち、どちらか一方にだけ含まれる要素の集合のことです。
ハット(^)やsymmetric_differenceメソッドを使用すると、対称差集合を作成できます。

s1 = {0, 1, 2}
s2 = {1, 2, 3}

s3 = s1 ^ s2
print(s3)

s4 = s1.symmetric_difference(s2)
print(s4)

このような2つの集合s1,s2の対称差集合を作成してみましょう。
ハット(^)を使用する場合は、2つの集合の間にハット(^)を記述します。
symmetric_differenceメソッドを使用する場合は、片方の集合のsymmetric_differenceメソッドを記述し、引数にもう一方の集合を指定します。
実行します。
対称差集合を作成できました。
どちらも同じ結果になっていることが確認できます。

集合の関係

次は、集合の関係について説明します。
集合Aが集合Bに含まれている時、集合Aは集合Bの部分集合と言います。
<=(小なりイコール)やissubsetメソッドを使用すると、部分集合かどうかを判定できます。

s1 = {0, 1, 2}
s2 = {0, 1, 2, 3, 4}

print(s1 <= s2)
print(s1.issubset(s2))

このような2つの集合を使用し、s1がs2の部分集合かどうかを判定してみましょう。
<=(小なりイコール)を使用する場合は、s1、<=(小なりイコール)、s2、と記述します。
issubsetメソッドを使用する場合は、s1のissubsetメソッドを記述し、引数にs2を指定します。
実行します。
どちらもTrueが返ってきました。
従って、s1はs2の部分集合であることがわかります。

また、集合Aの要素と集合Bの要素が全て一致する時、集合Aと集合Bは等しいと言います。
==(イコール2つ)を使用すると、集合が等しいかどうかを判定できます。

s1 = {0, 1, 2}
s2 = {0, 1, 2, 3, 4}
s3 = {2, 1, 0}

print(s1 == s2)
print(s1 == s3)

このような集合を使用し、s1とs2が等しいかどうか、s1とs3が等しいかどうかを判定してみましょう。
実行します。
s1とs2は等しくないのでFalseが返ってきます。
s1とs3は等しいのでTrueが返ってきます。
なお、集合には要素の順番はないため、要素の順序は判定に影響しません。

また、集合Aが集合Bの部分集合で,かつ、集合Bと等しくない時、集合Aは集合Bの真部分集合と言います。
<(小なり)を使用すると、真部分集合かどうかを判定できます。

s1 = {0, 1, 2}
s2 = {0, 1, 2, 3, 4}
s3 = {2, 1, 0}

print(s1 < s2)
print(s1 < s3)

このような集合を使用し、s1がs2の真部分集合かどうか、s1がs3の真部分集合かどうかを判定してみましょう。
実行します。
TrueとFalseが返ってきました。
s1はs2の部分集合であり、かつ、s2と等しくないため、s1はs2の真部分集合になります。
s1はs3の部分集合ですが、s3と等しいため、真部分集合ではありません。

更に、集合Aの要素と集合Bの要素が一つも一致しない場合、集合Aと集合Bは互いに素と言います。
isdisjointメソッドを使用すると、互いに素かどうかを判定できます。

s1 = {0, 1, 2}
s2 = {3, 4, 5}
s3 = {2, 3, 4}

print(s1.isdisjoint(s2))
print(s1.isdisjoint(s3))

このような集合を使用し、s1とs2が互いに素かどうか、s1とs3が互いに素かどうかを判定してみましょう。
s1のisdisjointメソッドを記述し、引数に相手方の集合を指定します。
実行します。
s1とs2は要素が全て異なり、互いに素であるためTrueが返ってきます。
s1とs3は一部要素が一致し、互いに素ではないためFalseが返ってきます。

要素の存在確認

集合でもリストと同じように演算子inを使用して、ある要素が集合に含まれているかどうかを確認できます。
inの左側に要素を、右側に集合を記述します。

s = {1, 2, 3, 4, 5}

print(1 in s)
print(0 in s)

このような集合を使用し、要素が集合に含まれているかどうか確認してみましょう。
実行します。
1は集合に含まれているのでTrueが返ってきます。
0は集合に含まれていないのでFalseが返ってきます。

要素の取得

集合には要素の順番がないため、インデックスを使用した要素の取り出しはできません。
集合の要素を取り出すにはfor文を使用します。
ただし、取り出す順序は要素の並び順とは限らないので注意しましょう。
それでは、for文で集合の要素を1つずつ取り出して表示してみましょう。

s = {4, 3, 2, 1}
for i in s:
    print(i)

forの後にカウンタ変数、続けてin、そして集合、最後にコロンを記述します。
インデントを下げてprint関数で要素を表示します。
実行します。
集合の要素を1つずつ取り出して表示できました。

その他の方法として、集合をリストに変換する方法があります。
リストに変換後は、for文やインデックスを使用して要素を取り出せます。
list関数を使用すると、集合をリストに変換できます。
それでは、集合をリストに変換し、インデックスを使用して指定した要素を取り出してみましょう。

s = {1, 2, 3, 4}
l = list(s)

print(l[0])

list関数の引数に集合を指定し、変数lに代入します。
lの0番目の要素を表示してみます。
実行します。
集合をリストに変換することでインデックスが使用可能になり、指定した要素を取り出すことができました。