タイトル: 要素の削除
SEOタイトル: Python リスト 要素の削除(pop / remove / del / clear 使い分け完全ガイド)
| この記事の要点 |
|
Python リスト要素の削除メソッド一覧
Python のリストから要素を削除する方法は複数あり、「インデックスで消すのか」「値で消すのか」「全部消すのか」で使うメソッドが異なります。本記事では pop() / remove() / del / clear() / 内包表記の 5 つを使い分けの観点から整理します。
| 方法 | 消すもの | 戻り値 | 該当なしの挙動 | 計算量 |
|---|---|---|---|---|
pop(i) | インデックス i の要素 | 削除した値 | IndexError | 末尾 O(1) / 途中 O(n) |
remove(x) | 最初に出現する値 x | None | ValueError | O(n) |
del lst[i] | インデックス / スライス | なし(文) | IndexError | O(n) |
clear() | 全要素 | None | 常に成功 | O(n) |
| 内包表記 | 条件にマッチした全要素 | 新しいリスト | マッチなしならコピー | O(n) |
pop() — インデックスで削除
pop() はインデックスを指定して要素を取り出しつつ削除します。引数を省略すると末尾を pop します(スタックの pop と同じ挙動)。
fruits = ["apple", "banana", "cherry", "durian"]
# 末尾を pop
last = fruits.pop()
print(last) # durian
print(fruits) # ['apple', 'banana', 'cherry']
# インデックス指定
second = fruits.pop(1)
print(second) # banana
print(fruits) # ['apple', 'cherry']
# 範囲外なら IndexError
fruits.pop(99) # IndexError: pop index out of range
使いどころ: スタック / キューとして「取り出して使う」とき。削除した値を後続処理で使う場合に最適。
remove() — 値で削除
remove(x) は最初にマッチした値だけを削除します。複数あっても先頭の 1 件しか消えません。
nums = [1, 2, 3, 2, 1]
nums.remove(2)
print(nums) # [1, 3, 2, 1] ← 後ろの 2 は残る
# 存在しない値は ValueError
nums.remove(99) # ValueError: list.remove(x): x not in list
# 安全に消したいなら in でチェック
if 99 in nums:
nums.remove(99)
全件削除したい場合は内包表記の方が高速かつ簡潔です(後述)。
del 文 — インデックス / スライス削除
del は組み込みの文(statement)で、インデックスでもスライスでも削除できます。連続した範囲を一気に消すなら del が最速。
lst = list(range(10)) # [0,1,2,3,4,5,6,7,8,9]
del lst[0] # 先頭削除
print(lst) # [1,2,3,4,5,6,7,8,9]
del lst[2:5] # スライス削除
print(lst) # [1,2,6,7,8,9]
del lst[::2] # ステップ付きスライス(偶数番削除)
print(lst) # [2,7,9]
del lst[:] # 全削除(lst.clear() と等価)
print(lst) # []
clear() — 中身を空にする
clear() はリストオブジェクトはそのままに、要素だけ全削除します。同じオブジェクトを参照している別変数にも反映される点が lst = [](再代入)との違いです。
a = [1, 2, 3]
b = a # 同じリストを参照
a.clear()
print(a) # []
print(b) # [] ← b も空になる
# 再代入だと参照が切れる
a = [1, 2, 3]
b = a
a = []
print(a) # []
print(b) # [1, 2, 3] ← b は元のまま
内包表記 — 条件にマッチした全件削除
remove() は 1 件しか消せないので、条件にマッチする全件を消したいときは内包表記でフィルタするのが Pythonic です。
nums = [1, 2, 3, 2, 4, 2, 5]
# 2 を全部消す(新しいリストを作る)
nums = [x for x in nums if x != 2]
print(nums) # [1, 3, 4, 5]
# 偶数だけ残す
nums = [x for x in range(10) if x % 2 == 0]
print(nums) # [0, 2, 4, 6, 8]
# 元のリストを書き換える(同じ id を保つ)
lst = [1, 2, 3, 2, 4]
lst[:] = [x for x in lst if x != 2]
print(lst) # [1, 3, 4]
ループ中の削除に注意
for ループでリストを回しながら削除すると要素をスキップします。インデックスがずれるためです。
# NG: 削除と同時にループ
nums = [1, 2, 2, 3, 2, 4]
for n in nums:
if n == 2:
nums.remove(n)
print(nums) # [1, 3, 2, 4] ← 2 が残る!
# OK: コピーをループ
nums = [1, 2, 2, 3, 2, 4]
for n in nums[:]: # スライスでコピー
if n == 2:
nums.remove(n)
print(nums) # [1, 3, 4]
# 最善: 内包表記
nums = [1, 2, 2, 3, 2, 4]
nums = [x for x in nums if x != 2]
FAQ
Q: pop() と del どちらが速い?
A: 削除した値が要らないなら del の方がわずかに速い(戻り値の生成コストがない)。値を使うなら pop()。
Q: 重複する値を全部消したい
A: while x in lst: lst.remove(x) はループになり遅い。内包表記 [v for v in lst if v != x] が最速。
Q: 削除のついでに index も知りたい
A: enumerate で index を取りつつ内包表記、または list(filter(...)) を使う。