
日々の作業でデータを扱っていると、「あれ、この値、前にもあったな」と感じる瞬間があります。
何度も同じ情報を処理して、無駄に時間が削られていく──そんな小さなストレスを減らしてくれるのがPythonの集合型(set)です。
重複を自動で取り除き、必要なものだけを残す。仕事もプログラムも、整理が進むほど心まで軽くなる仕組みです。
Pythonの基礎知識(基礎編)
🟣 Pythonの基礎知識(基礎編)
📌基本文法から実用テクニックまで、Pythonの土台を固めるステップアップ講座
└─ 【Pythonの基礎知識(基礎編)】仕組みから学ぶ思考と自動化のプログラミング講座
├─ STEP 0:Pythonを動かす“仕組み”を理解する
| ├─【Pythonの基礎知識】Pythonを動かす環境とは何か? “自分専用の環境”を作る
| ├─【Pythonの基礎知識】Hello Worldの裏側にある実行の仕組み
| └─【Pythonの基礎知識】Pythonのファイル構造と実行パスを理解する
|
├─STEP 1:Pythonで“考える仕組み”を作る(思考編)
| ├─【Pythonの基礎知識】データ型で世界を定義する|数・文字・真偽の正体
| ├─【Pythonの基礎知識】変数と値の動きを通して仕組みを理解しよう
| ├─【Pythonの基礎知識】条件分岐で“判断を任せる”仕組みを作る
| ├─【Pythonの基礎知識】for文で“人の手”を離す仕組みを作る
| └─【Pythonの基礎知識】while文で“継続する仕組み”を作る
|
├─STEP 2:Pythonで“情報を扱う仕組み”を作る(構造編)
| ├─【Pythonの基礎知識】コレクション型の正しい選び方(list, tuple, dict, set)
| ├─【Pythonの基礎知識】リストで情報を整理し、仕組みに流れを持たせる
| ├─【Pythonの基礎知識】辞書型でデータを“意味”で管理する
| └─【Pythonの基礎知識】集合型で重複を排除し、無駄をなくす仕組みを作る
|
├─STEP 3:Pythonで“動きを再利用する仕組み”を作る(関数・モジュール編)
| ├─【Pythonの基礎知識】関数で処理を再利用する|“人間の手順”を仕組みに変える
| ├─【Pythonの基礎知識】引数と戻り値で“情報のやりとり”を自動化する
| ├─【Pythonの基礎知識】モジュールとパッケージで“仕組みを部品化”する
| └─【Pythonの基礎知識】importの裏側を理解し、コードを分離する設計思考
|
├─STEP 4:Pythonで“データを扱う仕組み”を作る(入出力・永続化編)
| ├─【Pythonの基礎知識】ファイル操作でデータを読み書きする仕組みを作る
| ├─【Pythonの基礎知識】CSVを自在に扱う仕組みを作る
| ├─【Pythonの基礎知識】JSONで構造化データを操る
| └─【Pythonの基礎知識】例外処理で“壊れない仕組み”を設計する
|
└─STEP 5:Pythonで“自動化する仕組み”を作る(応用実践編)
├─【Pythonの基礎知識】スクリプトを自動実行させる仕組みを作る
├─【Pythonの基礎知識】日次タスクを自動化して人の時間を解放する
├─【Pythonの基礎知識】外部APIを活用して作業を外部化する
└─【Pythonの基礎知識】ログを記録して仕組みの信頼性を高める
集合型(set)による重複排除の必要性

日々のデータ処理の中で、同じ情報が何度も混ざり込んでしまうことは少なくありません。
最初は気づかなくても、集計結果がズレたり、レポートが膨れ上がったりして、あとから大きな修正が必要になることがあります。
Pythonの集合型(set)は、そんな「重複」という無駄を自然に取り除く仕組みを持っています。
データをきれいに整えるだけでなく、処理そのものをシンプルに保てるという利点があります。
わざわざ集合型を使う意味ってあるのかな?
重複データがもたらす無駄の実例
データ分析の現場では、CSVファイルやログなどから同じユーザーIDや商品名が何度も出現することがあります。
たとえば、リストを使ってアクセス履歴を記録すると、同じユーザーが何度も登場することになります。
users = ["taro", "hanako", "taro", "jiro", "hanako"] print(users)
【出力例:】
['taro', 'hanako', 'taro', 'jiro', 'hanako']
このまま集計をすると、「taro」や「hanako」が重複して数えられてしまい、正確な結果が得られません。
しかし、これを集合型に変換すれば、同じ値は自動的に1つにまとめられます。
unique_users = set(users)
print(unique_users)
【出力例:】
{'jiro', 'taro', 'hanako'}
データが少ないうちは違いが分かりづらいですが、数万件を超えるような処理では、この「重複を排除するひと手間」が、処理速度とメモリ使用量の差としてはっきり表れます。
setを使うことで得られる効果と制約
集合型の最大のメリットは、データの唯一性を保証できることです。
これにより、同じデータを何度も処理したり、不要な比較を行ったりする手間を減らせます。
さらに、集合型には数学的な発想に基づいた「和・差・積」などの演算があり、データの関係性を簡潔に表現できます。
a = {"apple", "banana", "orange"}
b = {"banana", "grape"}
print(a - b) # 差集合
print(a & b) # 積集合
print(a | b) # 和集合
【出力例:】
{'apple', 'orange'}
{'banana'}
{'banana', 'apple', 'grape', 'orange'}
ただし、集合型には注意点もあります。
順序を持たないため、リストのように「最初の要素」「最後の要素」を指定して扱うことはできません。
また、リストや辞書のような可変オブジェクトは要素として格納できないという制約もあります。
こうした仕様を理解して使えば、集合型は「データを整えるための最初の一歩」として大きな力を発揮します。
無駄をなくし、整ったデータを扱う。それだけでコード全体の流れがすっきりと見えてくるはずです。
Pythonにおける集合型の基本仕様

集合型(set)は、Pythonが持つ“重複を許さないデータ構造”です。
似たような情報が増えやすい実務の中で、これほど便利な型はありません。
特にログ集計やアクセス解析のような場面では、同じデータが何度も出てくるため、setの仕組みを知るだけでコードがぐっと整います。
set/frozensetの定義と特徴
Pythonには、可変な集合型「set」と、不変な集合型「frozenset」の2種類があります。
通常のsetは、あとから要素を追加・削除できますが、frozensetは作成後に変更できません。
変更の必要がないデータを扱うときには、frozensetを使うと安全です。
# setの基本定義
fruits = {"apple", "banana", "orange"}
print(fruits)
【出力例:】
{'orange', 'banana', 'apple'}
# frozensetの定義
frozen = frozenset(["apple", "banana", "orange"])
print(frozen)
【出力例:】
frozenset({'orange', 'banana', 'apple'})
setはリストのように順序を持たず、同じ要素を2回追加しても1つにまとめられます。
これにより、無駄な重複処理を排除しながら、データをクリーンに保つことができます。
あとで取り出すときに順番が変わってることってある?
重複排除・演算(和・差・積)とその利用例
集合型は、データをただ「一意に保つ」だけではありません。
数学の集合と同じように、和(union)・差(difference)・積(intersection)といった演算をサポートしています。
これにより、複数のデータ群の関係を一行で表せます。
a = {"apple", "banana", "orange"}
b = {"banana", "grape"}
print(a | b) # 和集合(どちらかに含まれる全て)
print(a & b) # 積集合(両方に含まれる要素)
print(a - b) # 差集合(aだけに含まれる要素)
【出力例:】
{'apple', 'banana', 'grape', 'orange'}
{'banana'}
{'apple', 'orange'}
このように、集合型はデータの重複を排除するだけでなく、複数のデータ群の「関係性」を整理する道具でもあります。
無駄をなくすという発想が、コードにも仕事にも余白を生む。
その感覚を一度体験すると、setを使わないコードにはもう戻れなくなるはずです。
実践:集合型を使った重複排除パターン

集合型(set)の仕組みを理解したら、次は実際にどんな場面で役立つのかを見ていきます。
重複のあるデータを一瞬で整理できるだけでなく、後続の処理も格段に楽になります。
面倒な重複チェックをループで回す必要はもうありません。
リスト→集合による変換で重複を除くコード例
リストには同じデータが混ざりやすく、特に外部ファイルやログから取り込んだデータでは重複がつきものです。
集合型を使えば、これを一瞬で整えることができます。
# 重複を含むリスト
users = ["taro", "hanako", "taro", "jiro", "hanako"]
集合に変換して重複を自動的に排除
unique_users = set(users)
print(unique_users)
【出力例:】
{'jiro', 'taro', 'hanako'}
変換するだけで、重複していたユーザー名がきれいに整理されました。
さらに、もう一度リスト形式に戻したい場合は、次のようにlist()で再変換するだけです。
users_list = list(unique_users)
print(users_list)
【出力例:】
['jiro', 'taro', 'hanako']
集合型は順序を保証しませんが、「同じ値を何度も処理する無駄」を一瞬で排除できます。
これは単なる便利機能ではなく、「整理されたデータから考える」ための基礎でもあります。
実体験:業務データ処理で集合型を導入したケース
以前、あるシステムのログ集計を担当していたとき、1日のアクセスログが10万件を超えていました。
最初はリストで扱っていましたが、重複データが多く、集計結果にズレが出ていました。
# 重複を含むアクセスログ例
access_logs = ["user01", "user02", "user01", "user03", "user02"]
集合に変換して一意なユーザーを抽出
unique_access = set(access_logs)
print(len(unique_access))
【出力例:】
3
集合型を導入してから、集計は一瞬で完了しました。
以前はfor文で重複をチェックしていたため、1万件を超えるデータでは処理に数十秒かかっていましたが、setを使うとわずか0.1秒で完了。しかもコードも短く、ミスが減りました。
たった数行で高速化できるなら、もっと早く知りたかった
このように、集合型は単なるデータ構造ではなく、「作業効率を根本から変える考え方」に近い存在です。
人間がデータを整理する時間を、Pythonが肩代わりしてくれる。だからこそ、現場のエンジニアほどsetをよく使います。
注意点と発展:集合型を使う上での落とし穴

集合型(set)はとても便利ですが、すべての場面で万能というわけではありません。
仕組みを正しく理解して使わないと、思わぬバグや挙動のズレにつながることがあります。
ここでは、setを扱う際に意識すべき制約と、そこから得られる発見について整理します。
それだけならどこでも使える気がするけど
要素がハッシュ可能であることの意味と制約
集合型に格納できるのは、ハッシュ化できる(hashable)オブジェクトだけです。
リストや辞書のように可変なデータは内部構造が変化するため、ハッシュ値が安定しません。
そのためsetの要素として登録できず、TypeErrorが発生します。
# 可変オブジェクト(リスト)を追加しようとするとエラー
data = {1, 2, 3}
data.add([4, 5])
【出力例:】
TypeError: unhashable type: 'list'
ハッシュ可能かどうかを確認するには、組み込み関数hash()を使うとわかりやすいです。
print(hash("apple")) # OK
print(hash((1, 2, 3))) # OK
print(hash([1, 2, 3])) # NG(リストはエラー)
【出力例:】
1779060509
529344067295497451
TypeError: unhashable type: 'list'
hash("apple") → OK(ハッシュ可能)
文字列(str)は一見、可変に見えますが、実はPythonでは不変(immutable)な型です。「apple」という文字列を変更することはできず、新しい文字列を作るしかありません。そのため、ハッシュ値(内部的な一意のIDのようなもの)を安全に計算できます。
print(hash("apple"))
【出力例:】
1779060509
文字列が同じなら、毎回同じハッシュ値が返ってきます。この「一貫性」が集合や辞書の内部での比較に使われています。
hash((1, 2, 3)) → OK(ハッシュ可能)
タプル(tuple)も不変型(immutable)なので、ハッシュ可能です。リストと似ていますが、タプルは一度作ると要素を変更できません。
そのため、Pythonは安心してハッシュ値を計算できます。
print(hash((1, 2, 3)))
【出力例:】
529344067295497451
ただし注意点があります。タプルの中に可変オブジェクト(例:リスト)が含まれていると、そのタプルもハッシュできなくなります。
print(hash((1, [2, 3])))
【出力例:】
TypeError: unhashable type: 'list'
hash([1, 2, 3]) → NG(ハッシュ不可)
リスト(list)は可変(mutable)なデータ型なので、ハッシュ化できません。中身をいつでも書き換えられるため、ハッシュ値が安定しないからです。
print(hash([1, 2, 3]))
【出力例:】
TypeError: unhashable type: 'list'
Pythonの設計思想として、「変わる可能性のあるデータにIDをつけて比較すると、後で矛盾が起きる」という考え方があるため、setやdictのキーにリストを使うことも禁止されています。
つまり、この3つの差は「変わらないものだけが、集合の一員になれる」という設計思想の表れです。
setやfrozensetが“正確にデータを扱う”ための根っこには、このハッシュの仕組みが隠れています。
Hash(ハッシュ)とは?
Pythonは、データを数値に変えるときに“乱数のタネ(seed)”を掛け合わせて計算します。 このタネ(seed)は、パソコンごとに違う「起動時間」や「システムの状態」など、その瞬間の環境情報をもとに自動で作られます。Pythonは「apple」という文字を見たとき、まずそれをUTF-8,16,32などの数字の列(97,112,112,108,101)に直します。そのあと、これらの数値を順番にseedと掛け合わせたり足し合わせたりして、一つの大きな数にまとめています。
だから、同じ "apple" をハッシュ化しても、 自分のパソコンと他の人のパソコンでは違う数字になります。 Pythonはこの仕組みで「ハッシュ値を予測されにくく」しており、 悪意ある攻撃(ハッシュ衝突攻撃)を防いでいます。 つまり、ハッシュは「いつも同じ結果になるもの」ではなく、 「その環境の中で同じデータを見分けるための番号」だと考えるのが正解です。
順序が保証されない/可変要素不可といった仕様からの気づき
集合型は順序を保持しないという特徴を持っています。つまり、追加した順番と出力の順番が一致する保証はありません。
これは欠点ではなく、「順序を気にせず一意性だけを扱う」ための仕組みです。
numbers = {10, 20, 30, 40}
numbers.add(50)
print(numbers)
【出力例:】
{40, 10, 50, 20, 30}
このように、順番が変わってもPythonは正しく動作しています。
setの目的は「データの整合性を保つこと」であり、並び順を保持することではありません。
また、集合型には変更不可のバージョンであるfrozensetも存在します。
データを「絶対に変更されたくない状態」で保持したい場合に使えます。
ログ分析やキャッシュのキーなど、安定性が求められる処理では重宝します。
frozen = frozenset(["A", "B", "C"])
print(frozen)
【出力例:】
frozenset({'A', 'B', 'C'})
集合型を深く理解するほど、Pythonが“無駄を削り、整合性を保つ”ためにどんな工夫をしているかが見えてきます。
setは、データを整えるだけでなく、「考え方を整える」ための道具でもあるのです。
まとめ
集合型(set)は、Pythonの中でも特に「整理」と「効率」に直結するデータ構造です。
重複を自動で取り除き、純粋なデータだけを残すことで、余計な処理や確認の手間を減らせます。
データの無駄をなくすことは、思考の無駄をなくすことでもあります。
setはただの構文ではなく、整理された仕事の形を教えてくれる仕組みです。
次のおすすめ記事
👉 【Pythonの基礎知識】関数で処理を再利用する|“人間の手順”を仕組みに変える
実践環境を整える
ここまで学んだ知識を実際に試すには、Linuxを動かす環境が必要です。手軽に始めるならVPSを利用するのがおすすめです。
→ VPS徹底比較!ConoHa・さくら・Xserverの選び方

