Python の集合(作成方法と基本操作)

Python の集合(set)は、重複しない要素の集まりを表すデータ型だ。数学の集合論をベースにしており、要素の順序は保証されない。

リテラルと set() による作成

集合を作る方法は 2 つある。波括弧 {} を使うリテラル記法と、set() コンストラクタだ。

# リテラル記法
fruits = {"apple", "banana", "cherry"}

# set() コンストラクタ
numbers = set([1, 2, 3, 4, 5])

ただし、空の集合を作る場合は注意が必要になる。{} は空の辞書(dict)として解釈されるため、空の集合には set() を使う。

empty_dict = {}      # これは辞書
empty_set = set()    # これが空の集合

print(type(empty_dict))  # <class 'dict'>
print(type(empty_set))   # <class 'set'>

この仕様は Python 2 時代からの互換性によるものだ。辞書のリテラル {} が先に存在していたため、空の波括弧は辞書として扱われる。

重複の自動排除

集合に同じ値を複数入れても、重複は自動的に排除される。

numbers = {1, 2, 2, 3, 3, 3}
print(numbers)  # {1, 2, 3}

リストから集合に変換すると、重複が除去された状態になる。これはデータのユニーク化によく使われるパターンだ。

items = ["a", "b", "a", "c", "b", "a"]
unique_items = set(items)
print(unique_items)  # {'a', 'b', 'c'}

要素として格納できるもの

集合にはハッシュ可能(hashable)なオブジェクトのみ格納できる。具体的には、イミュータブル(不変)な型が対象となる。

格納できる型

int, float, str, tuple, frozenset, bool, None

格納できない型

list, dict, set(ミュータブルな型)

リストを集合に入れようとすると TypeError が発生する。

s = {[1, 2, 3]}  # TypeError: unhashable type: 'list'

タプルは格納できるが、タプル内にリストが含まれる場合は不可だ。

s = {(1, 2, 3)}        # OK
s = {(1, [2, 3])}      # TypeError: unhashable type: 'list'

集合の基本情報

集合の要素数は len() で取得する。

s = {1, 2, 3, 4, 5}
print(len(s))  # 5

空かどうかの判定は、len() を使うか、集合をそのまま真偽値として評価できる。

s = set()
if not s:
    print("集合は空")

if len(s) == 0:
    print("集合は空")

Python では空のコレクションは偽(False)として評価されるため、if not s: という書き方が自然だ。

文字列からの集合作成

文字列を set() に渡すと、1 文字ずつ分解されて集合になる。

chars = set("hello")
print(chars)  # {'h', 'e', 'l', 'o'}

重複する文字は 1 つにまとめられる。文字列中のユニークな文字を調べたいときに便利だ。

イテラブルからの変換

set() は任意のイテラブルを受け取れる。リスト、タプル、range、ジェネレータなど、反復可能なオブジェクトなら何でも変換できる。

# range から
s1 = set(range(5))  # {0, 1, 2, 3, 4}

# タプルから
s2 = set((1, 2, 3))  # {1, 2, 3}

# ジェネレータから
s3 = set(x * 2 for x in range(3))  # {0, 2, 4}

ジェネレータ式をそのまま渡せるため、メモリ効率を意識した集合作成も可能になる。