連載
» 2019年06月25日 05時00分 公開

Python入門:[Python入門]集合 (1/4)

Pythonでは「集合」も標準でサポートされている。その基本と、集合の比較や和/差/積/対称差の求め方、変更不可能な集合などについて見ていこう。

[かわさきしんじ,Deep Insider編集部]
「Python入門」のインデックス

連載目次

 前回までに、Pythonで多数のデータを一括して扱うためのデータ構造としてリスト、タプル、辞書を紹介してきた。今回は、Pythonが組み込みで提供しているそうしたデータ構造の最後の一つである「集合」を取り上げる。

集合とは

 Pythonにおける「集合」(set)は、数学の集合と似たものだ。つまり、何らかの値が寄り集まったものを表現する。その性質としては、1つの集合には同じ要素が含まれないことと、集合の要素には順番がない(整数値のインデックスを使って、特定の要素を指すことができない)ことが挙げられる。

集合 集合

 集合は、ある集合に特定の要素が含まれているかを調べたり、ある集合と別の集合を比較したりする目的で使用できる。そのために、集合の和、差、積などを計算するメソッドや演算子が用意されている。

 例えば、特定のユーザーにどのような権限や役割が割り当てられているかを調べたり、リストやタプル、辞書から重複する値を取り除くために集合を使ったりすることが考えられる。

集合の定義

 集合は辞書と同様に波かっこ「{}」を使って表現する。

Pythonの集合 Pythonの集合

 波かっこを使うことは、前回に紹介した辞書と同様だ。ただし、こちらは「キーと値」の組ではなく、その要素をそのまま{}に囲んで表記する。以下に集合を定義する例を示す。

mylanguages = {'Python', 'Ruby', 'PHP'}
print(mylanguages)

集合の定義例

 先ほども述べたように集合では要素は重複しない。つまり、ある集合を定義する際に同じ要素を複数記述しても、それらは1つにまとめられる。

mylanguages = {'Python', 'Ruby', 'PHP', 'Python'}
print(mylanguages)

集合では同じ要素が重複することはない

 上の2つのコード例の実行結果を以下に示す。両者の結果が同じことに注目しよう。

集合では要素が重複しない 集合では要素が重複しない

 ここで集合を定義したときの要素の並び順と、それをprint関数で表示したときの並び順が異なることに気が付いたかもしれない。リストやタプルでは、そこに要素を追加した順に整数値のインデックスが付加されていた。リストやタプルのように、追加順が記憶され、整数値のインデックスを使って特定の要素を指定できることをPythonでは「順序を持つ」「順序性がある」などといい、この特性を持ったデータ型を「シーケンス」などと呼ぶ(リストやタプルに加えて、文字列もそうだ)。

 これに対して、本稿で取り上げている集合には「順序がない」といえる。追加順序は内部では保持されないので、集合に要素を追加した順序とは異なる表示になることもある(同じ場合もある)。同様に、辞書も「常に」整数インデックスが使えるわけではないので、「順序がない」と考えられる。Python 3.7以降では、辞書にキーと値の組を追加すると、その追加順が内部で維持されるものの、整数値でインデックス指定ができないことに変わりはないからだ。

 通常の集合(上の手順で作成する集合)に対しては、要素を追加したり、要素を削除したりできる。つまり、変更可能(ミュータブル)だ。これに対して、要素の追加や削除ができないイミュータブルな集合もある。これをPythonでは「frozenset」と呼ぶ。これについては本稿の最後で軽く触れることにしよう。

set関数による集合の定義

 これまでに見てきたリストやタプル、辞書と同様に、集合を定義するための関数もある。それがset関数だ。

set関数

set([iterable])


 iterableを基に集合を作成する。iterableを省略したときには空の集合が作られる。

パラメーター 説明
iterable 集合を定義するのに利用する反復可能オブジェクト(省略可能)。省略時には空の集合が作られる
set関数のパラメーター


 空の集合を定義するには、set関数を引数なしで呼び出す必要がある。波かっこ「{}」のみでは空の辞書ができてしまうからだ。

emptyset = {}  # 実は空の辞書の作成
print(type(emptyset))
emptyset = set()  # 空の集合の作成
print(emptyset)
print(type(emptyset))

空の集合を作成するには引数なしでset関数を呼び出す

 以下に実行結果を示す。

実行結果 実行結果

 波かっこ「{}」によって作成したオブジェクトの型が「<class 'dict'>」になっていることと、set関数によって作成したオブジェクトの型が「<class 'set'>」になっている点に注目しよう。

 set関数に反復可能オブジェクトを渡した場合、それを基に集合が作成される。このとき、反復可能オブジェクトに重複する要素があれば、それらは1つの要素にまとめられる。以下に例を示す。

mylist = [1, 2, 3] * 2  # [1, 2, 3, 1, 2, 3]
myset = set(mylist)
print(myset)
mydict = {'foo': 'FOO', 'bar': 'BAR'}
myset = set(mydict)  # mydictのキーを要素とする集合
print(myset)
myset = set(mydict.items())  # mydictの(キー, 値)のタプルを要素とする集合
print(myset)

set関数の使用例

 実行結果を以下に示す。

実行結果 実行結果

 最初の呼び出しでは「[1, 2, 3, 1, 2, 3]」というリストをset関数に渡しているが、できた集合は「{1, 2, 3}」と同じ要素が重複していないことに注目しよう。次の呼び出しでは辞書のキーを要素とした集合ができている。最後の呼び出しでは辞書のitemsメソッドを使ってビューオブジェクトを渡しているが、これによりキーと値の組をタプルとしたものが集合の要素になっている。

集合の内包表記

 リストや辞書と同様に、集合でも内包表記が使える(タプルだけは内包表記による記述ができない)。内包表記の基本形を以下に示す。

集合の内包表記

{集合の要素を算出する式 for ループ変数 in 反復可能オブジェクト}



 最後にif節を追加したり、for節をネストしたりもできるが、上に示したのが集合の内包表記の基本形だ。以下に例を示す。

myset = {x for x in range(10)}  # 0〜9の整数値を要素とする集合
print(myset)

myset = {x for x in range(10) if x % 2 == 0# 0〜8の範囲に含まれる偶数値
print(myset)

集合の内包表記の例

 ただし、最初の「{x for x in range(10)}」はset関数を使って、「set(range(10))」と書いた方が簡単だし、次の「{x for x in range(10) if x % 2 == 0}」も「set(range(0, 10, 2))」とより簡潔に書ける(例なのでご容赦願いたい)。実行結果を以下に示す。

実行結果 実行結果

       1|2|3|4 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。