

私の質問の概要は、リスト内包表記で文字列から複数の不要な文字列を除去する処理の書き方です。

例えば、

[code]

    "a皆a様aよbろbしbくcおc願cいcしNULLまNULLす。"
    
[/code]

から不要な["a","b","c","NULL"]を除去して

[code]

    "皆様よろしくお願いします。"
    
[/code]

を得るために

[code]

    words = "a皆a様aよbろbしbくcおc願cいしNULLまNULLす。"
    alist = ["a", "b", "c","NULL"]
    for delstr in alist:
        words = words.replace(delstr, "")
    
[/code]

という処理をしています。しかし、wordsは多数存在し、alistも巨大なため、リスト内包表記で高速化が出来ないかと考え、以下のようなコードを書きました。

[code]

    [words.replace(delstr, "") for delstr in alist]
    
[/code]

しかし、これではwordsからalistのそれぞれの要素を除去したリストが得られてしまうため、目的を果たせません。

一つの方法は上記のwordsをリスト内包表記にしてalistの要素をループ毎にwordsのリストから除去する方法ですが、もし内包表記で単一のオブジェクトに複数の処理ことができるならばwordsのリストとalistを一括して内包表記にできるため、より望ましいと考えています。wordsからalistの要素すべてをリスト内包表記で除去する方法があればご教示頂ければ幸いです。


CC BY-SA 4.0
2018-09-21T10:01:38.277
48622
2018-09-22T03:03:42.327
2018-09-21T11:39:43.583
30198
30198
question
python
list内包表記で単一の文字列から複数の文字列を取り除く方法はあるでしょうか


[`re.sub`](https://docs.python.jp/3/library/re.html#re.sub) を使う案です。

[code]

    import re
    words_re = re.compile("|".join(re.escape(w) for w in alist))
    result = re.sub(words_re, '', words)
    
[/code]

削除文字列（`alist`）の内容によっては `replace` を繰り返した場合とは違う結果になるので注意して下さい。例えば、

[code]

    words = "<abc>"
    alist = ["b", "abc"]
    
[/code]

だとすると、`replace` では `b` の削除のみが起こり結果は `<ac>`で、正規表現だと先に `abc` のマッチが始まるので `abc`
が削除され結果は `<>` になります。


CC BY-SA 4.0
2018-09-21T10:26:37.317
48623
2018-09-21T12:52:07.233
2018-09-21T12:52:07.233
3054
3054
48622
answer


高階関数の`functools.reduce`を使うと1行で書くことができます。  
<https://docs.python.org/ja/3/howto/functional.html#the-functools-module>

[code]

    def func(a, b):
      return a.replace(b, "")
    
    words = "a皆a様aよbろbしbくcおc願cいしNULLまNULLす。"
    alist = ["a", "b", "c","NULL"]
    functools.reduce(func, alist, words)
    
[/code]

これをラムダ式を使って書くと

[code]

    functools.reduce(lambda a, b:a.replace(b, ""), alist, words)
    
[/code]

ただし、ドキュメントには、「多くの場合 functools.reduce() を使うよりは、単に for
ループを書いたほうがわかりやすくなります」とあります。


CC BY-SA 4.0
2018-09-22T03:03:42.327
48634
2018-09-22T03:03:42.327
15171
48622
answer