最初に、正規表現またはstr.translate(...)
ベースのソリューションが最もパフォーマンスが高いことを他の人に同意したいと思います。私のユースケースでは、この関数のパフォーマンスはそれほど重要ではなかったので、その基準で検討したアイデアを追加したいと思いました。
私の主な目的は、他のいくつかの回答からのアイデアを、正規表現以外の単語を含む文字列で機能する1つのソリューションに一般化することでした(つまり、句読文字の明示的なサブセットのブラックリストと単語文字のホワイトリスト)。
どのアプローチでもstring.punctuation
、手動で定義したリストの代わりに使用することを検討する場合があることに注意してください。
オプション1-re.sub
今のところre.sub(...)を使用しているので、答えが見つからないことに驚きました。私はそれがこの問題へのシンプルで自然なアプローチだと思います。
import re
my_str = "Hey, you - what are you doing here!?"
words = re.split(r'\s+', re.sub(r'[,\-!?]', ' ', my_str).strip())
このソリューションでは、re.sub(...)
内部への呼び出しを入れ子にしましたre.split(...)
—パフォーマンスが重要な場合、外部で正規表現をコンパイルすることは有益かもしれません—私の使用例では、違いは重要ではなかったので、単純さと読みやすさを優先します。
オプション2-str.replace
これはさらに数行ですが、正規表現で特定の文字をエスケープする必要があるかどうかを確認する必要なく拡張できるという利点があります。
my_str = "Hey, you - what are you doing here!?"
replacements = (',', '-', '!', '?')
for r in replacements:
my_str = my_str.replace(r, ' ')
words = my_str.split()
代わりにstr.replaceを文字列にマップできれば良かったのですが、不変の文字列では実行できないと思います。文字のリストに対するマッピングは機能しますが、すべての文字に対してすべての置換を実行します過度に聞こえます。(編集:機能例については、次のオプションを参照してください。)
オプション3-functools.reduce
(Python 2では、reduce
functoolsからインポートせずにグローバル名前空間で使用できます。)
import functools
my_str = "Hey, you - what are you doing here!?"
replacements = (',', '-', '!', '?')
my_str = functools.reduce(lambda s, sep: s.replace(sep, ' '), replacements, my_str)
words = my_str.split()