こんにちは、かつコーチです。
これまでリスト・タプル・辞書を解説してきましたが、今回はセット(set)を取り上げます。
セットとは、重複した値を持たない、順序のないデータ構造のことです。
「リストから重複を取り除きたいだけなのに、自分でループを書いて頑張っていた」というのが、私がセットの便利さに気づく前の状態でした。
この記事では、セットの作成方法(重複排除)と、和集合・積集合・差集合といった集合演算の使い方を解説します。
基本の書き方:セットの作成と重複排除
セットを作成する
セットは{}(波かっこ)、またはset()関数で作成します。
fruits = {"りんご", "みかん", "ぶどう"}
print(fruits)
# {'ぶどう', 'みかん', 'りんご'}
出力順序が入力順と異なる点に注意してください。
セットには「順序」という概念がないため、表示順は保証されません。
空のセットを作るときは、{}ではなくset()を使う必要があります。
empty_dict = {}
print(type(empty_dict))
# <class 'dict'>
empty_set = set()
print(type(empty_set))
# <class 'set'>
{}は辞書の空リテラルとして扱われるため、セットのつもりで書くと型を間違えてしまいます。
重複を排除する
セットの大きな用途の1つが、リストから重複を取り除くことです。
numbers = [1, 2, 2, 3, 3, 3, 4]
unique_numbers = set(numbers)
print(unique_numbers)
# {1, 2, 3, 4}
リストに戻したい場合は、list()で変換します。
unique_list = list(unique_numbers)
print(unique_list)
# [1, 2, 3, 4]
要素の追加・削除
要素の追加はadd()、削除はremove()またはdiscard()を使います。
fruits.add("メロン")
fruits.remove("みかん")
print(fruits)
# {'ぶどう', 'りんご', 'メロン'}
つまずきやすい設定・注意点
セットに追加できるのは、リストや辞書のように変更可能な値ではなく、タプルなどのイミュータブルな値に限られます。
group = {(1, 2), (3, 4)}
これはOKですが、リストをセットに入れようとするとエラーになります。
group = {[1, 2], [3, 4]}
TypeError: unhashable type: 'list'
よくあるつまずきポイント・エラー対処
remove()で存在しない値を削除しようとしてエラーになる
❌ Before:remove()をそのまま使う
私が最初にセットを使ったとき、ユーザーのタグ一覧から特定のタグを削除する処理で、次のように書いていました。
tags = {"python", "web", "初心者"}
tags.remove("django")
「django」タグは実際には登録されていなかったため、実行時に次のエラーが発生しました。
KeyError: 'django'
リストのremove()はValueErrorでしたが、セットのremove()はKeyErrorになる点にも戸惑いました。
✅ After:discard()を使うか、事前にin演算子で確認する
存在しない値を削除しようとしてもエラーにしたくない場合は、discard()を使います。
tags = {"python", "web", "初心者"}
tags.discard("django")
print(tags)
# {'python', 'web', '初心者'}
discard()は、値が存在しなくても何も起こらずに処理が続行されます。
エラーの発生自体をロジックとして使いたい場合はremove()、安全に処理を続けたい場合はdiscard()、という使い分けを覚えておくと安心です。
応用:集合演算の使い方
セットの真価は、数学の集合演算をそのままコードで表現できる点にあります。
set_a = {1, 2, 3, 4}
set_b = {3, 4, 5, 6}
和集合(どちらかに含まれる要素)
print(set_a | set_b)
# {1, 2, 3, 4, 5, 6}
print(set_a.union(set_b))
# {1, 2, 3, 4, 5, 6}
積集合(両方に共通する要素)
print(set_a & set_b)
# {3, 4}
print(set_a.intersection(set_b))
# {3, 4}
差集合(片方にしかない要素)
print(set_a - set_b)
# {1, 2}
print(set_a.difference(set_b))
# {1, 2}
例えば「昨日のログインユーザー」と「今日のログインユーザー」のセットを作り、差集合を取れば「今日だけ来たユーザー」を一瞬で求められます。
ループで比較処理を書くよりも、圧倒的に短く読みやすいコードになります。
まとめ
この記事のポイント
- セットは
{}またはset()で作成し、重複した値を持てない - 空のセットは
{}ではなくset()で作成する - 要素の追加は
add()、削除はremove()またはdiscard() remove()は存在しない値の削除でKeyErrorになるため注意する- 和集合
|・積集合&・差集合-を使えば、重複比較の処理が簡潔に書ける
次に読むべき記事
データ構造の基本を一通り押さえたら、次は処理を再利用できる仕組みである「関数」の定義方法を学んでいきましょう。
→ 次の記事:関数の定義と引数(デフォルト引数・可変長引数)
タグ: Python, 初心者向け, 基本文法
