415

Pythonを使用して、文字列から英数字以外のすべての文字を削除する最良の方法は何ですか?

この質問のPHPバリアントで提示されたソリューションは、おそらくいくつかの小さな調整で機能しますが、私にはあまり「pythonic」とは思えません。

記録のために、ピリオドとコンマ (およびその他の句読点) だけでなく、引用符、括弧なども削除したいと考えています。

4

15 に答える 15

410

好奇心からいくつかの機能の時間を計測しました。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
于 2009-08-14T10:03:32.190 に答える
340

救助のための正規表現:

import re
re.sub(r'\W+', '', your_string)

Pythonの定義による'\W== [^a-zA-Z0-9_]、これはすべてを除外しnumbersletters_

于 2009-08-14T08:57:37.767 に答える
76

メソッドを使用しstr.translate()ます。

これを頻繁に行うと仮定すると、次のようになります。

  1. 一度、削除したいすべての文字を含む文字列を作成します。

    delchars = ''.join(c for c in map(chr, range(256)) if not c.isalnum())
    
  2. 文字列をスクランチしたいときはいつでも:

    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
于 2009-08-15T00:33:48.707 に答える
53

あなたは試すことができます:

print ''.join(ch for ch in some_string if ch.isalnum())
于 2009-08-14T09:02:28.413 に答える
18
>>> import re
>>> string = "Kl13@£$%[};'\""
>>> pattern = re.compile('\W')
>>> string = re.sub(pattern, '', string)
>>> print string
Kl13
于 2009-08-14T09:01:22.860 に答える
15

どうですか:

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_lettersdigits

于 2009-08-14T08:58:39.700 に答える
6

ここでの他の回答からのスピンオフとして、文字列のコンテンツを制限する文字セットを定義するための非常にシンプルで柔軟な方法を提供します。この場合、英数字に加えてダッシュとアンダースコアを使用できます。PERMITTED_CHARSユースケース に合わせて、 my から文字を追加または削除するだけです。

PERMITTED_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-" 
someString = "".join(c for c in someString if c in PERMITTED_CHARS)
于 2017-03-13T12:54:22.387 に答える