Pythonでリストの重複を簡単に取り除くならset
が便利です。
setは重複を持たない集合型で、順序に依存しないデータを扱うのに向いています。
本記事ではPython初心者向けに、setの作り方から基本操作、重複削除の一行テクニック、注意点まで丁寧に解説します。
Pythonのsetとは?重複しない集合
setの特徴(重複なし・順序なし)
setは数学の集合のように、同じ値を2つ以上含みません。
つまり、重複が自動で排除されるのが最大の特徴です。
また、setには順序がありません。
そのため、リストのようにインデックスで要素にアクセスすることはできません。
setの主な性質は次の通りです。
順序がないため表示順は不定となり、プログラムの実行ごとに並びが変わる場合があります。
要素はミュータブルである必要はなく、ハッシュ可能な型のみが要素にできます。
具体的には数値、文字列、タプルなどはOKですが、リストや辞書はNGです。
重複除去や集合演算に強い一方、順序を保ったまま処理したい用途には向きません。
# setの基本性質: 重複は自動で1つにまとまる、順序はない
s = {1, 2, 2, 3, 3, 3} # 同じ値を複数書いてもOK
print(s) # 順序は保証されない
print(len(s)) # 要素数は重複を除いた数
print(2 in s) # 含まれるかどうか
{1, 2, 3}
3
True
setの作り方(リストからsetへ)
リストからsetを作るにはset(リスト)
を使います。
これだけで重複が取り除かれます。
# リストからsetを生成して重複を除去する例
colors = ["red", "blue", "red", "green", "blue"]
unique_colors = set(colors)
print(unique_colors) # 順序は不定
print(type(unique_colors)) # <class 'set'>
{'blue', 'green', 'red'}
<class 'set'>
コンソールに表示される並び順は実行環境によって変わる点に注意してください。
空のsetを作る(set)
空のsetはset()
で作ります。
{}は空の辞書(dict)になるので要注意です。
# 空のsetの作り方
empty_braces = {} # これは空のdict
print(type(empty_braces))
empty_set = set() # こちらが空のset
print(empty_set)
print(type(empty_set))
<class 'dict'>
set()
<class 'set'>
空集合は必ずset()
を使うのが正解です。
リストの重複を削除する方法(set)
一行で重複削除(list->set->list)
リストの重複を削除する最短手はlist(set(リスト))
です。
これで重複が消えた新しいリストが得られます。
# 一行で重複を除去する
nums = [3, 1, 2, 3, 2, 1]
deduped = list(set(nums)) # setで重複削除 → listに戻す
print(deduped) # 並び順は不定
print(len(deduped)) # 3
[1, 2, 3]
3
とにかく重複を消したいだけならこの一行で十分です。
順序が変わる点に注意
setは順序を持たないため、listに戻したときの並び順は元の順序と一致しません。
順序を安定させたい場合は、用途に応じて次の方法を使い分けます。
- ソートして安定化する: 値の大小で並び替えてよい場合は
sorted(set(リスト))
を使います。 - 元の出現順を保つ: 走査しながら
seen
という補助setを使って重複をスキップします。
# 並び順をソートで安定化する
nums = [3, 1, 2, 3, 2, 1]
print(sorted(set(nums))) # [1, 2, 3]
# 元の出現順を保って重複除去する
nums = [3, 1, 2, 3, 2, 1]
seen = set()
deduped_stable = []
for x in nums:
if x not in seen:
deduped_stable.append(x) # 初出だけ追加
seen.add(x)
print(deduped_stable) # [3, 1, 2]
[1, 2, 3]
[3, 1, 2]
順序が重要かどうかで手段を選ぶのがポイントです。
文字列の重複も削除できる
setは文字列のリストにも使えます。
大文字小文字は別の要素として扱われます。
# 文字列の重複を削除する
words = ["Apple", "banana", "apple", "Banana", "banana"]
unique_words = list(set(words)) # 順序は不定
print(unique_words)
# 大文字小文字を無視して重複を消すには lower を使う
unique_lower = list({w.lower() for w in words}) # set内包表記
print(unique_lower) # ['banana', 'apple'] など
['banana', 'apple', 'Banana', 'Apple']
['banana', 'apple']
正規化(例: lower()
)してからset化すると意図した重複判定ができます。
setの基本操作(初心者向け)
要素を追加する(add)
要素を1つ追加するにはadd
を使います。
既にある値を追加しても何も起きません。
# addで要素を追加
s = {1, 2}
s.add(3) # {1, 2, 3}
s.add(2) # 既存要素は追加しても変化なし
print(s)
{1, 2, 3}
複数要素をまとめて追加したい場合はupdate(iterable)
が使えます。
要素を削除する(removeとdiscard)
remove(x)
は存在しない要素を指定するとKeyError
になります。
エラーにしたくないならdiscard(x)
を使います。
# remove と discard の違い
s = {1, 2, 3}
s.remove(2)
print(s) # {1, 3}
# 存在しない要素の remove は例外
try:
s.remove(99)
except KeyError as e:
print("KeyError:", e)
# discard は存在しなくても何もしない
s.discard(99)
print("after discard:", s)
{1, 3}
KeyError: 99
after discard: {1, 3}
以下の表が使い分けの要点です。
メソッド | 存在しない要素を指定したとき |
---|---|
remove(x) | KeyError例外を送出 |
discard(x) | 何もしない(エラーなし) |
安全に書きたいときはdiscard
、存在を保証したいときはremove
を選ぶと覚えるとよいです。
含まれるか調べる(in)
in
演算子で要素の存在をO(1)程度で高速に判定できます。
検索用途にも向いています。
# in 演算子でメンバーシップ判定
s = {"red", "green"}
print("red" in s) # True
print("blue" in s) # False
True
False
setはメンバーシップ判定が高速なので、フィルタや重複チェックに最適です。
要素数を数える(len)
len
で要素数を取得できます。
もちろん重複は数えられません。
# len で要素数を取得
s = {"a", "b", "a"} # 'a' は重複
print(s) # {'a', 'b'}
print(len(s)) # 2
{'b', 'a'}
2
setの注意点とよくあるエラー
インデックス指定はできない
setは順序がないためs[0]
のようなインデックスアクセスはできません。
TypeErrorとなります。
要素を1つ取り出したい場合はiter
でイテレータを作り、next
を使います。
# インデックスアクセスは不可
s = {10, 20, 30}
# print(s[0]) # TypeError: 'set' object is not subscriptable
# 1つだけ取り出すなら iter と next を使う
first = next(iter(s))
print(first)
10
表示される値はどれになるか保証されません。
特定の順序で取りたい場合はリストに変換してソートするなどの対処が必要です。
リストは要素にできない
setの要素はハッシュ可能である必要があります。
リストはミュータブルなためハッシュ不可能で、要素に加えようとするとエラーになります。
代わりにタプルやfrozenset
を使います。
# リストは要素にできない
s = set()
try:
s.add([1, 2]) # TypeError
except TypeError as e:
print("TypeError:", e)
# 代わりにタプルを使う
s.add((1, 2))
print(s)
# 集合を要素にしたいなら frozenset を使う
t = set()
t.add(frozenset({1, 2})) # 不変集合はハッシュ可能
print(t)
TypeError: unhashable type: 'list'
{(1, 2)}
{frozenset({1, 2})}
可変なオブジェクトはsetの要素にできないという原則を覚えておきましょう。
重複は自動で1つにまとまる
setでは同じ要素を何度追加しても1つにまとまります。
これは重複除去の源泉です。
# 同じ値の追加は無視される
s = set()
s.add(1)
s.add(1)
s.add(1)
print(s, len(s)) # {1} 1
{1} 1
重複チェックのためのif文を書かなくても、setに入れるだけで重複が消えるのが便利です。
まとめ
本記事では、Pythonのset
について、重複なし・順序なしという基本性質から、リストからの生成、空集合の作り方、重複削除の実践方法、一行テクニック、基本操作と注意点までを解説しました。
重複をなくしたい、要素の存在を高速に確かめたいという場面では、setは最有力の選択肢です。
一方で順序が必要な処理にはそのまま使えないため、必要に応じてsorted
や補助のseen
集合を組み合わせて使うのがコツです。
まずはlist(set(x))
で重複を落とすところから始め、add
、discard
、in
、len
といった基本操作を身につけて、データ前処理や検索の効率化に役立ててください。