この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:T
更新日時:2026-06-11 07:12:00

タイトル: セット
SEOタイトル: Python set (集合) 型完全ガイド(リテラル・和差積・frozenset・内包表記)

この記事の要点
  • Python の set重複を許さない順序なしコレクション。要素の存在判定 inO(1)
  • リテラル {1, 2, 3}、空セットは set() ({} は辞書になる)
  • 集合演算: |&-対称差 ^
  • 主要メソッド: add / remove / discard / pop / update / issubset / issuperset
  • 不変版は frozenset辞書のキーや set の要素として使える

set とは

Python の set は数学の「集合」に相当するデータ型で、次の特徴を持ちます。

  • 重複なし: 同じ値は 1 つしか保持しない
  • 順序なし: 要素の並び順を保証しない (Python 3.7+ でも保証しない)
  • ハッシュ可能な要素のみ: int / str / tuple は OK、list / dict は NG
  • in 演算が O(1) 平均: list の O(N) に対して圧倒的に速い

作成方法

# リテラル
s1 = {1, 2, 3}
s2 = {'apple', 'banana'}

# set() コンストラクタ
s3 = set([1, 2, 3])         # list から
s4 = set('hello')           # 文字列から → {'h', 'e', 'l', 'o'} (l は重複削除)
s5 = set(range(5))          # range から → {0, 1, 2, 3, 4}

# 空セット
empty = set()               # ✅
wrong = {}                  # ❌ これは空の dict

# 集合内包表記
squares = {x ** 2 for x in range(10)}   # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}

# 重複は自動的に除外される
nums = {1, 2, 2, 3, 3, 3}   # → {1, 2, 3}

集合演算 (union / intersection / difference / symmetric_difference)

演算演算子メソッド意味
和集合A | BA.union(B)どちらかに含まれる
積集合A & BA.intersection(B)両方に含まれる
差集合A - BA.difference(B)A にあって B にない
対称差A ^ BA.symmetric_difference(B)どちらか片方にだけ
部分集合A <= BA.issubset(B)A が B の部分集合か
真部分集合A < BA ⊂ B かつ A ≠ B
上位集合A >= BA.issuperset(B)A が B を含むか
互いに素A.isdisjoint(B)共通要素なし
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

A | B   # {1, 2, 3, 4, 5, 6}
A & B   # {3, 4}
A - B   # {1, 2}
B - A   # {5, 6}
A ^ B   # {1, 2, 5, 6}

A <= {1, 2, 3, 4, 5}   # True (A は部分集合)
A.isdisjoint({10, 20}) # True

更新メソッド

s = {1, 2, 3}

s.add(4)            # → {1, 2, 3, 4}
s.add(2)            # 重複は無視 (エラーにならない)

s.remove(3)         # → {1, 2, 4}    存在しない要素だと KeyError
s.discard(99)       # 存在しなくてもエラーにならない (推奨)

popped = s.pop()    # 任意の 1 要素を取り出して削除 (順序不定)

s.clear()           # 空にする

# 破壊的集合演算
s = {1, 2, 3}
s |= {3, 4, 5}      # update      → {1, 2, 3, 4, 5}
s &amp;= {2, 4, 6}      # intersection_update → {2, 4}
s -= {2}            # difference_update   → {4}
s ^= {4, 7}         # symmetric_difference_update → {7}

典型ユースケース 1: 重複削除

# list の重複削除 (順序不問)
nums = [1, 2, 2, 3, 3, 3, 4]
unique = list(set(nums))   # [1, 2, 3, 4] (順序は保証されない)

# 順序を保ちつつ重複削除 (Python 3.7+ dict)
unique_ordered = list(dict.fromkeys(nums))   # [1, 2, 3, 4]

典型ユースケース 2: 高速な存在判定 (O(1))

# ❌ list の in は O(N)
allowed_ids = [1, 2, 3, ..., 1_000_000]
if user_id in allowed_ids:   # 最悪 100 万回比較
    ...

# ✅ set の in は O(1)
allowed_ids = {1, 2, 3, ..., 1_000_000}
if user_id in allowed_ids:   # ハッシュ参照 1 回
    ...

# 2 つのリストの共通要素を取得
common = set(list_a) &amp; set(list_b)

典型ユースケース 3: 集合演算でフィルタ

# DB から取得した既存ユーザ ID と、リクエストで来た新規 ID
existing = {1, 2, 3, 4, 5}
incoming = {3, 4, 5, 6, 7}

to_insert = incoming - existing   # {6, 7}    INSERT すべきもの
to_delete = existing - incoming   # {1, 2}    DELETE すべきもの
to_update = incoming &amp; existing   # {3, 4, 5} UPDATE すべきもの

frozenset (不変な集合)

set はハッシュ不可なので辞書のキーや set の要素にできません。frozenset は不変なのでハッシュ可能、辞書のキーや set の要素として使えます。

fs = frozenset([1, 2, 3])
fs.add(4)   # ❌ AttributeError: 'frozenset' object has no attribute 'add'

# 集合演算は通常の set と同じ
fs | {4, 5}    # frozenset({1, 2, 3, 4, 5})

# 辞書のキーに使える
groups = {
    frozenset({1, 2}): 'group A',
    frozenset({3, 4}): 'group B',
}

# set の要素として使える (set of sets)
set_of_sets = {frozenset({1, 2}), frozenset({3, 4})}

set に入れられない型

# ハッシュ可能でない型は要素にできない
s = {[1, 2]}      # ❌ TypeError: unhashable type: 'list'
s = {{1: 2}}      # ❌ TypeError: unhashable type: 'dict'
s = {{1, 2}}      # ❌ TypeError: unhashable type: 'set'

# tuple は OK (不変なのでハッシュ可)
s = {(1, 2), (3, 4)}   # ✅

計算量まとめ

操作setlist
x in sO(1)O(N)
s.add(x) / s.remove(x)O(1)O(N)
反復 (for)O(N)O(N)
和差積O(N+M)
順序保持×
index アクセス×O(1)

FAQ

Q: 順序を保ちたい set はある?
A: 標準にはありません。dict.fromkeys(seq) で代用するか、collections.OrderedDictsortedcontainers.SortedSet (サードパーティ) を使います。

Q: set のソート出力は?
A: sorted(s) で list を返します。set 自体はソートできません。

Q: 巨大データで set のメモリ使用量が気になる
A: set は dict と同じく要素 1 つあたり数十バイトのオーバーヘッド。1000 万件超なら array / NumPy / Bloom filter 等の検討を。