1. リストからリストの要素を削除する

簡単そうな処理だけれども地味に悩んだ処理。

調べてみると質問サイトに同じような質問があるので同様の悩みを持つ方も多そう。2014年頃の昔の質問も見つかります。

実装として4つの方法が見つかりました。

  1. for文のなかでremove

  2. リスト内包表記

  3. 組み込み関数のfilter

  4. set:集合演算

検討した結果、要素の削除であれば set:集合演算 を使用する方法で良さそうという結論になりました。

元のリストに重複がある場合に集合演算は使えないとも考えたのですがそもそもそのような状況はなさそうだということでsetを使用する方法が一番だという結論になりました。

要素を削除するのではなくNoneなど別の値に変換する場合には setでは対応できないのでその場合はリスト内包表記やfilterで対応 できます。

for文の中でremoveする方法 は削除対象側のリストに重複がある場合や削除される側に要素がない場合にエラーが発生するので 使い勝手が悪いです。

2. 実装

4つの方法を実装してみます。

2.1. データ作成

要素の重複や要素がない状況のため4つのデータを作成します。

aが削除される側でb, c, dが削除対象です。

src.py
a = [1, 2, 3, 4, 5, 6]
b = [3, 4, 5]
c = [3, 3, 4]
d = [6, 7, 8]

2.2. for文のなかでremove

  削除対象がc, dの場合にエラーが発生するのでおすすめできない実装方法です。

src.py
def for_remove(x, y):
    z = x.copy()
    for i in y:
        z.remove(i)
    return z

for_remove(a, b)
for_remove(a, c)
for_remove(a, d)
error
ValueError: list.remove(x): x not in list

2.3. リスト内包表記

要素の置換時にも使用できます。

リストが大きい場合には処理時間がかかってしまうので要素の削除が目的ならsetによる方法を使用したほうが早いでしょう。

src.py
def list_comprehension(x, y):
    return [
        i for i in x
        if i not in y
    ]

list_comprehension(a, b)
list_comprehension(a, c)
list_comprehension(a, d)

2.4. 組み込み関数のfilter

使い勝手はリスト内包表記と同じようなものです。

返り値がジェネレータなのでpythonらしい実装なのかもしれません。

src.py
list(filter(lambda x: x not in b, a))
list(filter(lambda x: x not in c, a))
list(filter(lambda x: x not in d, a))

2.5. set:集合演算

要素の削除や差分が目的ならsetがおすすめです。

src.py
set(a).difference(set(b))
set(a).difference(set(c))
set(a).difference(set(d))

3. まとめ

リスト要素の削除の実装方法について整理しました。

削除した要素が欲しい場合にはset、要素の置換が目的の場合はリスト内包表記やfilterがおすすめです。

for文のなかでremoveする方法は要素によってエラーが発生するのでおすすめできません。

今回は以上です。