こんにちは。
Pythonで使用するシーケンスには「文字列」「 range()
」 「 list()
」「 tuple()
」などがあります。
これらはオブジェクト = データが格納庫に番号が振られた順番に沿って収納されており、その格納庫をスライスする事で取り出す事もできました。
しかし、シーケンスの親戚の様なもので、格納されているオブジェクトに順序がなく番号が振られていないものもあります。
それが以下の2つです。
- セット(集合)
- 辞書
今回はこのうち、「セット」に関するイロハ、すなわち① セット(集合)と② 辞書について学んでいきたいと思います。
本記事の学習内容
- セットについて
- Pythonにおけるセットを利用した応用方法
- セットの作成方法
- セットの四則演算と集合演算
では早速、見ていきましょう。
セット(set)について
セットとは集合体を意味します。
例えば、喫煙する人や、BMI>25の方など、集合体そのものを表すものであり、セットの中に格納されているオブジェクトには厳密に番号は割り振られていません。
また、喫煙する方が、「田中 太郎」さんであった場合、同姓同名の方がセットの中にいるとしても同一人物を2重に入れる事はできません。
さらに、セットの性質として、数学で学ぶ集合計算を用いた計算方法(和集合や積集合)を用いる事が出来ますので、色々な応用を行う事ができます。
早速セットの使用方法について見ていきましょう。
セットの基本的な使用方法
基本的なセット {}
の使用方法
セットを使用する際には { }
を利用します。
リストは[ ]
やタプルは( )
でしたので、復習しておきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | >>> x = {"a" ,"b", "c", "d", "e"} >>> y = {"sanka", "fujinka", "seisixyoku", "jixyoseiigaku"} >>> z = {1, "a", 2, "b", 3, "c", 4} >>> w = {} >>> print(x) {'a', 'b', 'd', 'e', 'c'} >>> print(y) {'sanka', 'fujinka', 'seisixyoku', 'jixyoseiigaku'} >>> print(z) {1, 2, 3, 4, 'a', 'b', 'c'} >>> print(w) {} >>> type(x) <class 'set'> >>> type(y) <class 'set'> >>> type(z) <class 'set'> >>> type(w) <class 'dict'> |
ここで重要な事は、上記のコードでもわかる様に、type(w)
は class 'dict'
となっています。
すなわち、w = {}
はクラスの意味ではなく辞書としての意味を持つので覚えておきましょう。
空の何も格納されていないリストは set()
と表記されます。次のコードでお示しします。
{}
以外にもset()
という標準関数の使い方も覚えておきましょう。
1 2 3 4 5 6 7 8 9 | >>> a = set("sanfujinkainotechou") >>> b = set(range(2, 18, 3)) >>> c = set() >>> print(a) {'i', 'a', 'j', 'o', 'k', 'n', 'h', 'e', 'c', 'u', 'f', 't', 's'} >>> print(b) {2, 5, 8, 11, 14, 17} >>> print(c) set() |
セットにおける内包表記の方法
この様に他のシーケンスと同様にセットでも内包表記を行う事が可能です。
内包表記として for文, if文, else文 等の構文も使用する事ができます。
1 2 3 | >>> num_dict = {num * 2 for num in range(4, 30, 2)} >>> print(num_dict) {32, 36, 8, 40, 12, 44, 16, 48, 20, 52, 24, 56, 28} |
セットの応用的な使用方法
セットの要素を追加する方法
セットの要素を追加する際にはadd()
メソッドを使用してください。
add()
の()
内部に文字列を挿入する際には " " で囲む様にしてください。
また同じドキュメントを追加しようとしても、重複して追加する事はできません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >>> medical_department = set() >>> medical_department.add("obgyn") >>> print(medical_department) {'obgyn'} >>> medical_department.add(surgery) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'surgery' is not defined >>> medical_department.add("surgery") >>> print(medical_department) {'obgyn', 'surgery'} >>> medical_department.add("urology") >>> medical_department.add("surgery") >>> print(medical_department) {'obgyn', 'surgery', 'urology'} |
セットに収納されている要素を取り出して参照する方法
セットに収納されている要素を取り出すためには pop()
メソッドを使用します。
pop()
メソッドは ()
で指定した位置の要素を削除し値を取得する、というメソッドです。
list
や tuple
などのシーケンスの時にはスライスを用いる事で参照する事ができましたが、set
の際には pop
メソッドを用いる様にしてください。
更に重要な事は、pop()
メソッドを使用すると格納されているドキュメントが取り出される分、消去されます。
また、引数なしの pop() は 0番目の値を取得します。
1 2 3 4 5 | >>> a = medical_department.pop() >>> print(a) obgyn >>> print(medical_department) {'surgery', 'urology'} |
上記の様に、引数のない pop()
は medical_department
の0番目の値を取得して a
に代入したので、 print(a)
とすると0番目の要素である obgyn
が出力されるわけです。
セットに収納されているドキュメントを削除、消去する方法
set()
で収納されているドキュメントを削除するメソッドには以下のものがあります。
remove()
: ドキュメントを削除する事が出来るが、既に削除されていたり、そもそも収納されていない場合には KeyError が出る。discard()
: ドキュメントを削除する事ができるメソッドだが、remove()
の様なKeyErrorは出ない。clear()
: 全てのドキュメントを消去したい際に用いるメソッド
では早速、remove()
, discard()
, clear()
のメソッドを使用してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | >>> medical_department = set() >>> medical_department.add("obgyn") >>> medical_department.add("surgery") >>> medical_department.add("urology") >>> medical_department.add("dermatology") >>> medical_department.add("cardiology") >>> print(medical_department) {'obgyn', 'urology', 'surgery', 'cardiology', 'dermatology'} >>> medical_department.remove("urology") >>> print(medical_department) {'obgyn', 'surgery', 'cardiology', 'dermatology'} >>> medical_department.remove("urology") Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'urology' >>> medical_department.discard("urology") >>> print(medical_department) {'obgyn', 'surgery', 'cardiology', 'dermatology'} >>> medical_department.clear() >>> print(medical_department) set() |
セットに収納したドキュメントを検索する方法
セット set() に収納されたドキュメントを検索する方法として、メソッドはなく、ドキュメントの有無の確認をするためには in
または not in
で確認を行います。
1 2 3 4 5 6 7 8 | >>> medical_department = set() >>> medical_department.add("obgyn") >>> medical_department.add("surgery") >>> medical_department.add("urology") >>> "urology" in medical_department True >>> "dermatology" not in medical_department True |
セットに収納したドキュメントを変更しない方法
セットで収納したものからドキュメントを削除、消去、追加したりはしたくない時には frozenset()
関数を使用すればドキュメントが固定されます。
格納されたドキュメントは変更不可能なため、色々なメソッドを使用しても変更する事はできません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> medical_department = set() >>> medical_department.add("obgyn") >>> medical_department.add("surgery") >>> medical_department.add("urology") >>> medical_department = frozenset(medical_department) >>> print(medical_department) frozenset({'obgyn', 'surgery', 'urology'}) >>> medical_department.remove("surgery") Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'frozenset' object has no attribute 'remove' |
セットの四則演算と集合演算
セットの和集合
セットで和集合の演算を行う際には、|
またはメソッドの union()
を使用します。
集合Aと集合Bの和集合はAUBで表現します。
» Wikipedia 和集合
ここで、medical department の 2つのgroup(mg1
, mg2
)で和集合の演算を行なってみましょう。
1 2 3 4 5 6 7 8 9 10 | >>> mg1 = {"obgyn", "urology", "surgery"} >>> mg1 = {"obgyn", "urology", "surgery"} >>> mg2 = {"pathology", "dermatology", "radiology"} >>> mg3 = mg1 | mg2 >>> print(mg3) {'radiology', 'obgyn', 'pathology', 'urology', 'surgery', 'dermatology'} >>> mg3 = mg1.union(mg2) >>> print(mg3) {'radiology', 'obgyn', 'pathology', 'urology', 'surgery', 'dermatology'} |
セットの積集合
セットの積集合は共通している部分の箇所を意味します。
集合Aと集合Bの積集合は $A ∩ B$ と表されます。
» Wikipedia 共通部分
積集合は演算子の &
を用いて表されます。また、メソッドは intersection()
となります。
和集合と同様に、medical department の 2つのgroup(mg1
, mg2
)で和集合の演算を行なってみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >>> mg1 = {"obgyn", "urology", "surgery"} >>> mg2 = {"pathology", "dermatology", "radiology"} >>> mg4 = mg1 & mg2 >>> print(mg4) set() >>> mg1 = {"obgyn", "urology", "surgery", "pathology"} >>> mg2 = {"pathology", "dermatology", "radiology", "obgyn"} >>> mg4 = mg1 & mg2 >>> print(mg4) {'obgyn', 'pathology'} >>> mg4 = mg1.intersection(mg2) >>> print(mg4) {'obgyn', 'pathology'} |
この様に積集合が存在しない時には、set()
と表されます。
セットの差集合
集合Aと集合Bの差集合とは、集合Aから集合Aと集合Bの共通部分(A ∩ B )を除いた集合を意味します。
ベン図で描いてみると分かりやすいです。
» Wikipedia 差集合
セットにおいても同様の性質があります。
差集合は -
で表現することができます。また、差集合のメソッドは difference()
です。
和集合や積集合と同様に、medical department の 2つのgroup(mg1
, mg2
)で差集合の演算を行なってみましょう。
1 2 3 4 5 6 7 8 9 10 11 | >>> mg1 = {"obgyn", "urology", "surgery", "pathology"} >>> mg2 = {"pathology", "dermatology", "radiology", "obgyn"} >>> mg5 = mg1 - mg2 >>> print(mg5) {'urology', 'surgery'} >>> mg1 = {"obgyn", "urology", "surgery", "pathology"} >>> mg2 = {"pathology", "dermatology", "radiology", "obgyn"} >>> mg5 = mg1.difference(mg2) >>> print(mg5) {'urology', 'surgery'} |
セットの対象差集合
集合Aと集合Bの対象差とは“A に属し、B に属さないもの” と “B に属し、A に属さないもの” とを全部集めて得られる集合である。
>> Wikipedia 対象差
セットでも対象差を求める事ができます。
対象差は ^ の演算子で求める事ができます。メソッドは symmetric_difference()
となります。
1 2 3 4 5 6 7 8 9 10 11 | >>> mg1 = {"obgyn", "urology", "surgery", "pathology"} >>> mg2 = {"pathology", "dermatology", "radiology", "obgyn"} >>> mg6 = mg1.symmetric_difference(mg2) >>> print(mg6) {'radiology', 'urology', 'surgery', 'dermatology'} >>> mg1 = {"obgyn", "urology", "surgery", "pathology"} >>> mg2 = {"pathology", "dermatology", "radiology", "obgyn"} >>> mg6 = mg1.symmetric_difference(mg2) >>> print(mg6) {'radiology', 'urology', 'surgery', 'dermatology'} |
集合演算における破壊的なメソッドと非破壊的なメソッド
和集合、積集合、差集合は全て非破壊的なメソッドで、mg1, mg2 は書き換わりませんでした。
和集合、積集合、差集合、対象差集合それぞれにおいて、非破壊的なメソッドと破壊的なメソッドがありますので、それぞれについてまとめておきます。
和集合
① 非破壊的 |
,メソッド union()
② 破壊的 |=
,メソッド update()
積集合
① 非破壊的 &
, メソッド interdection()
② 破壊的 &=
, メソッド intersection_update()
差集合
① 非破壊的 -
, difference()
② 破壊的 -=
, difference_update()
対象差集合
① 非破壊的 ^
, symmetric_difference()
② 破壊的 ^=
, symmetric_difference_update()
セットの部分集合
ある集合Aが他の集合Bに含まれている時には、集合Aは集合Bの部分集合と言います。
>> Wikipedia 部分集合
あるセットAが他のセットBの部分集合担っているのかどうかを調べる際には issubset()
メソッドで調べます。
また、あるセットAが他のセットBに完全に含まれているのかどうかは issuperset()
で調べる事ができます。
1 2 3 4 5 6 | >>> mg7 = {"obgyn", "urology"} >>> mg8 = {"pathology", "dermatology", "radiology", "obgyn", "urology"} >>> mg7.issubset(mg8) True >>> mg8.issuperset(mg7) True |
セットに共通した要素の有無を調べる
集合Aと集合Bの共通した集合は積集合と言いました。
集合Aと集合Bに共通した集合があるのかないのか、のみを調べる場合には indisjoint() メソッドで調べる事ができます。
- 共通した要素がある時には
False
- 共通した要素がない時には
True
となります。
1 2 3 4 | >>> mg7 = {"obgyn", "urology"} >>> mg8 = {"pathology", "dermatology", "radiology", "obgyn", "urology"} >>> mg7.isdisjoint(mg8) False |
まとめ|セットについての基本から応用までを解説
今回はセットに関する内容をほぼ全て網羅して解説しました。
少し難しい内容もあるかと思いますが、シーケンスとは異なる特徴を持ったセットに関する内容の理解が出来たのではないかと思います。
今回は以上となります。