Pythonの基礎知識(基礎編)

【Pythonの基礎知識】集合型で重複を排除し、無駄をなくす仕組みを作る

日々の作業でデータを扱っていると、「あれ、この値、前にもあったな」と感じる瞬間があります。

何度も同じ情報を処理して、無駄に時間が削られていく──そんな小さなストレスを減らしてくれるのが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)は、そんな「重複」という無駄を自然に取り除く仕組みを持っています。

データをきれいに整えるだけでなく、処理そのものをシンプルに保てるという利点があります。

リストを使えば十分じゃないの?

わざわざ集合型を使う意味ってあるのかな?

同じデータを何度も扱うと、無駄な処理が増えてパフォーマンスが下がります。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つにまとめられます。

これにより、無駄な重複処理を排除しながら、データをクリーンに保つことができます。

順番がなくなるのはちょっと困るかも。

あとで取り出すときに順番が変わってることってある?

そうですね。setは順序を保証しません。ただ、順番が重要な場合はリストを使うべきで、setは“唯一性の確保”が目的なんです。どちらを使うかを切り替えられると、処理の正確さが変わります。

重複排除・演算(和・差・積)とその利用例

集合型は、データをただ「一意に保つ」だけではありません。

数学の集合と同じように、和(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)の仕組みを理解したら、次は実際にどんな場面で役立つのかを見ていきます。

重複のあるデータを一瞬で整理できるだけでなく、後続の処理も格段に楽になります。

面倒な重複チェックをループで回す必要はもうありません。

リストの中身を手動で確認して重複を消してるけど、もっと早い方法ってあるの?
あります。集合型を使えば、一行で終わります。Pythonが自動的に重複を排除してくれるので、目で確認する必要がなくなるんです。

リスト→集合による変換で重複を除くコード例

リストには同じデータが混ざりやすく、特に外部ファイルやログから取り込んだデータでは重複がつきものです。

集合型を使えば、これを一瞬で整えることができます。

# 重複を含むリスト
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']

集合型は順序を保証しませんが、「同じ値を何度も処理する無駄」を一瞬で排除できます。

これは単なる便利機能ではなく、「整理されたデータから考える」ための基礎でもあります。

確かにすっきりしてるね。でも順番が変わるのが少し不安かも
その場合は、最後にsort()で並び替えれば大丈夫です。大切なのは、まず重複を消してから整列するという順序を覚えることです。

実体験:業務データ処理で集合型を導入したケース

以前、あるシステムのログ集計を担当していたとき、1日のアクセスログが10万件を超えていました。

最初はリストで扱っていましたが、重複データが多く、集計結果にズレが出ていました。

# 重複を含むアクセスログ例
access_logs = ["user01", "user02", "user01", "user03", "user02"]

集合に変換して一意なユーザーを抽出

unique_access = set(access_logs)
print(len(unique_access))

【出力例:】

3

集合型を導入してから、集計は一瞬で完了しました。

以前はfor文で重複をチェックしていたため、1万件を超えるデータでは処理に数十秒かかっていましたが、setを使うとわずか0.1秒で完了。しかもコードも短く、ミスが減りました。

そんなに変わるの?

たった数行で高速化できるなら、もっと早く知りたかった

集合型の強みは、シンプルさと正確さの両立です。余分な処理を減らすことで、CPUにもメモリにも優しいコードになります。

このように、集合型は単なるデータ構造ではなく、「作業効率を根本から変える考え方」に近い存在です。

人間がデータを整理する時間を、Pythonが肩代わりしてくれる。だからこそ、現場のエンジニアほどsetをよく使います。

注意点と発展:集合型を使う上での落とし穴

集合型(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のキーにリストを使うことも禁止されています。

見た目は同じようなデータなのに、タプルだけOKってなんか不思議だね
そこがポイントなんです。Pythonは「変わらないもの=信用できる」と判断してハッシュを計算します。逆にリストのように後から変えられるものは、集合に入れても整合性が崩れるので弾かれるんです。

つまり、この3つの差は「変わらないものだけが、集合の一員になれる」という設計思想の表れです。

setやfrozensetが“正確にデータを扱う”ための根っこには、このハッシュの仕組みが隠れています。

Hash(ハッシュ)とは?
Pythonは、データを数値に変えるときに“乱数のタネ(seed)”を掛け合わせて計算します。 このタネ(seed)は、パソコンごとに違う「起動時間」や「システムの状態」など、その瞬間の環境情報をもとに自動で作られます。Pythonは「apple」という文字を見たとき、まずそれをUTF-8,16,32などの数字の列(97,112,112,108,101)に直します。そのあと、これらの数値を順番にseedと掛け合わせたり足し合わせたりして、一つの大きな数にまとめています。
だから、同じ "apple" をハッシュ化しても、 自分のパソコンと他の人のパソコンでは違う数字になります。 Pythonはこの仕組みで「ハッシュ値を予測されにくく」しており、 悪意ある攻撃(ハッシュ衝突攻撃)を防いでいます。 つまり、ハッシュは「いつも同じ結果になるもの」ではなく、 「その環境の中で同じデータを見分けるための番号」だと考えるのが正解です。

なるほど、人間が商品番号で在庫を管理するのと同じってことか。
そうです。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の魅力です。日々の処理に取り入れるだけで、結果も作業時間も確実に変わります。

データの無駄をなくすことは、思考の無駄をなくすことでもあります。

setはただの構文ではなく、整理された仕事の形を教えてくれる仕組みです。

次のおすすめ記事

よく読まれている記事

1

「私たちが日々利用しているスマートフォンやインターネット、そしてスーパーコンピュータやクラウドサービス――これらの多くがLinuxの力で動いていることをご存じですか? 無料で使えるだけでなく、高い柔軟 ...

2

Linux環境でよく目にする「Vim」という名前。サーバーにログインしたら突然Vimが開いてしまい、「どうやって入力するの?」「保存や終了ができない!」と困った経験をした人も多いのではないでしょうか。 ...

3

ネットワーク技術は現代のITインフラにおいて不可欠な要素となっています。しかし、ネットワークを深く理解するためには、その基本となる「プロトコル」と「レイヤ」の概念をしっかり把握することが重要です。 こ ...

4

この記事は、Linuxについて勉強している初心者の方向けに「Shellスクリプト」について解説します。最後まで読んで頂けましたら、Shellスクリプトはどのような役割を担っているのか?を理解出来るよう ...

5

Javaは世界中で広く使われているプログラミング言語であり、特に業務システムやWebアプリケーションの開発において欠かせない存在です。本記事では、初心者向けにJavaの基礎知識を網羅し、環境構築から基 ...

-Pythonの基礎知識(基礎編)