Pythonを使用して、文字列から英数字以外のすべての文字を削除する最良の方法は何ですか?
この質問のPHPバリアントで提示されたソリューションは、おそらくいくつかの小さな調整で機能しますが、私にはあまり「pythonic」とは思えません。
記録のために、ピリオドとコンマ (およびその他の句読点) だけでなく、引用符、括弧なども削除したいと考えています。
Pythonを使用して、文字列から英数字以外のすべての文字を削除する最良の方法は何ですか?
この質問のPHPバリアントで提示されたソリューションは、おそらくいくつかの小さな調整で機能しますが、私にはあまり「pythonic」とは思えません。
記録のために、ピリオドとコンマ (およびその他の句読点) だけでなく、引用符、括弧なども削除したいと考えています。
好奇心からいくつかの機能の時間を計測しました。string.printable
これらのテストでは、文字列(組み込みstring
モジュールの一部)から英数字以外の文字を削除しています。コンパイル済みの使用が最速であることがわかりました'[\W_]+'
。pattern.sub('', str)
$ python -m timeit -s \
"import string" \
"''.join(ch for ch in string.printable if ch.isalnum())"
10000 loops, best of 3: 57.6 usec per loop
$ python -m timeit -s \
"import string" \
"filter(str.isalnum, string.printable)"
10000 loops, best of 3: 37.9 usec per loop
$ python -m timeit -s \
"import re, string" \
"re.sub('[\W_]', '', string.printable)"
10000 loops, best of 3: 27.5 usec per loop
$ python -m timeit -s \
"import re, string" \
"re.sub('[\W_]+', '', string.printable)"
100000 loops, best of 3: 15 usec per loop
$ python -m timeit -s \
"import re, string; pattern = re.compile('[\W_]+')" \
"pattern.sub('', string.printable)"
100000 loops, best of 3: 11.2 usec per loop
救助のための正規表現:
import re
re.sub(r'\W+', '', your_string)
Pythonの定義による
'\W
==[^a-zA-Z0-9_]
、これはすべてを除外しnumbers
、letters
_
メソッドを使用しstr.translate()
ます。
これを頻繁に行うと仮定すると、次のようになります。
一度、削除したいすべての文字を含む文字列を作成します。
delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
文字列をスクランチしたいときはいつでも:
scrunched = s.translate(None, delchars)
セットアップ コストは、おそらく に匹敵しre.compile
ます。限界費用ははるかに低くなります。
C:\junk>\python26\python -mtimeit -s"import string;d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s=string.printable" "s.translate(None,d)"
100000 loops, best of 3: 2.04 usec per loop
C:\junk>\python26\python -mtimeit -s"import re,string;s=string.printable;r=re.compile(r'[\W_]+')" "r.sub('',s)"
100000 loops, best of 3: 7.34 usec per loop
注:ベンチマーク データとして使用すると、パターンが不当に有利string.printable
'[\W_]+'
になります。英数字以外の文字はすべて 1 つの束に含まれています...典型的なデータでは、複数の置換を行う必要があります。
C:\junk>\python26\python -c "import string; s = string.printable; print len(s),repr(s)"
100 '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
re.sub
もう少し作業を行うと、次のようになります。
C:\junk>\python26\python -mtimeit -s"d=''.join(c for c in map(chr,range(256)) if not c.isalnum());s='foo-'*25" "s.translate(None,d)"
1000000 loops, best of 3: 1.97 usec per loop
C:\junk>\python26\python -mtimeit -s"import re;s='foo-'*25;r=re.compile(r'[\W_]+')" "r.sub('',s)"
10000 loops, best of 3: 26.4 usec per loop
あなたは試すことができます:
print ''.join(ch for ch in some_string if ch.isalnum())
>>> import re
>>> string = "Kl13@£$%[};'\""
>>> pattern = re.compile('\W')
>>> string = re.sub(pattern, '', string)
>>> print string
Kl13
どうですか:
def ExtractAlphanumeric(InputString):
from string import ascii_letters, digits
return "".join([ch for ch in InputString if ch in (ascii_letters + digits)])
これは、リスト内包表記を使用して、結合された文字列に文字が存在する場合に文字のリストを生成することによって機能しInputString
ます。次に、リストを1つの文字列に結合します。ascii_letters
digits
ここでの他の回答からのスピンオフとして、文字列のコンテンツを制限する文字セットを定義するための非常にシンプルで柔軟な方法を提供します。この場合、英数字に加えてダッシュとアンダースコアを使用できます。PERMITTED_CHARS
ユースケース に合わせて、 my から文字を追加または削除するだけです。
PERMITTED_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"
someString = "".join(c for c in someString if c in PERMITTED_CHARS)