文字列から数字以外のすべての文字を削除するにはどうすればよいですか?
文字列から数字以外のすべての文字を削除するにはどうすればよいですか?
回答:
Python 2. *では、最も速いアプローチは.translate
メソッドです。
>>> x='aaa12333bb445bb54b5b52'
>>> import string
>>> all=string.maketrans('','')
>>> nodigs=all.translate(all, string.digits)
>>> x.translate(all, nodigs)
'1233344554552'
>>>
string.maketrans
変換テーブル(長さ256の文字列)を作成します。この場合、''.join(chr(x) for x in range(256))
(作成するのがより速い;-) と同じです。.translate
変換テーブル(all
基本的にはIDを意味するため、ここでは関係ありません)を適用し、2番目の引数(キー部分)にある文字を削除します。
.translate
Unicode文字列(およびPython 3の文字列)ではまったく異なる動作をしますメジャーリリースに関心があるを質問に明記して!)-非常に単純ではありませんが、それほど高速ではありませんが、まだかなり使用可能です。
2. *に戻ると、パフォーマンスの違いは印象的です...:
$ python -mtimeit -s'import string; all=string.maketrans("", ""); nodig=all.translate(all, string.digits); x="aaa12333bb445bb54b5b52"' 'x.translate(all, nodig)'
1000000 loops, best of 3: 1.04 usec per loop
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 7.9 usec per loop
物事を7-8倍高速化することはほとんどピーナッツではないので、このtranslate
方法は知って使用する価値があります。他の一般的な非REアプローチ...:
$ python -mtimeit -s'x="aaa12333bb445bb54b5b52"' '"".join(i for i in x if i.isdigit())'
100000 loops, best of 3: 11.5 usec per loop
REはREより50%遅いため、.translate
アプローチはそれを1桁以上上回ります。
Python 3では、またはUnicodeの場合、削除するもの.translate
に対して返すマッピング(キーではなく、文字ではなく序数を使用)を渡す必要がありNone
ます。これは、「すべてを除く」数文字を削除するためにこれを表現する便利な方法です。
import string
class Del:
def __init__(self, keep=string.digits):
self.comp = dict((ord(c),c) for c in keep)
def __getitem__(self, k):
return self.comp.get(k)
DD = Del()
x='aaa12333bb445bb54b5b52'
x.translate(DD)
も放出し'1233344554552'
ます。しかし、これをxx.pyに入れると...:
$ python3.1 -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000 loops, best of 3: 8.43 usec per loop
$ python3.1 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
10000 loops, best of 3: 24.3 usec per loop
...この種の「削除」タスクでは、パフォーマンスの利点が失われ、パフォーマンスが低下することを示しています。
x.translate(None, string.digits)
実際の結果は'aaabbbbbb'
、意図したものとは逆になります。
all
組み込みをオーバーライドしています...それについては不明です!
次のre.sub
ように使用します:
>>> import re
>>> re.sub('\D', '', 'aas30dsa20')
'3020'
\D
数字以外の文字に一致するので、上記のコードは基本的に、空の文字列の数字以外のすべての文字を置き換えます。
またはfilter
、次のように使用できます(Python 2の場合):
>>> filter(str.isdigit, 'aas30dsa20')
'3020'
Python 3 filter
ではの代わりにイテレータを返すため、代わりにlist
次のコードを使用できます。
>>> ''.join(filter(str.isdigit, 'aas30dsa20'))
'3020'
isdigit
、ジェネレーターisdigt
はその中間にあります
r
文字列に使用する:re.sub(r"\D+", "", "aas30dsa20")
s=''.join(i for i in s if i.isdigit())
別のジェネレーターバリアント。
フィルターを使用できます:
filter(lambda x: x.isdigit(), "dasdasd2313dsa")
python3.0では、これに参加する必要があります(ちょっと醜い:()
''.join(filter(lambda x: x.isdigit(), "dasdasd2313dsa"))
str
ためlist
に変換します。– ''.join(filter(lambda x: x.isdigit(), list("dasdasd2313dsa")))
x.translate(None, string.digits)
文字列からすべての数字を削除します。文字を削除して数字を保持するには、次のようにします。
x.translate(None, string.letters)
TypeError
:translate()が引数を1つだけ受け取ります(2つ与えられます)。この質問が現在の状態で賛成された理由は非常にイライラします。
opはコメントで彼が小数点以下を保持したいと述べています。これは、保持する文字を明示的にリストすることで、re.subメソッド(2番目およびIMHOベストアンサーに従って)で実行できます。
>>> re.sub("[^0123456789\.]","","poo123.4and5fish")
'123.45'
Python 3の高速バージョン:
# xx3.py
from collections import defaultdict
import string
_NoneType = type(None)
def keeper(keep):
table = defaultdict(_NoneType)
table.update({ord(c): c for c in keep})
return table
digit_keeper = keeper(string.digits)
次に、正規表現とパフォーマンスの比較を示します。
$ python3.3 -mtimeit -s'import xx3; x="aaa12333bb445bb54b5b52"' 'x.translate(xx3.digit_keeper)'
1000000 loops, best of 3: 1.02 usec per loop
$ python3.3 -mtimeit -s'import re; r = re.compile(r"\D"); x="aaa12333bb445bb54b5b52"' 'r.sub("", x)'
100000 loops, best of 3: 3.43 usec per loop
ですから、私にとっては正規表現よりも3倍以上高速です。また、class Del
上記よりも高速です。defaultdict
(遅い)Pythonではなく、すべてのルックアップをCで行うです。比較のために、同じシステムでのそのバージョンを以下に示します。
$ python3.3 -mtimeit -s'import xx; x="aaa12333bb445bb54b5b52"' 'x.translate(xx.DD)'
100000 loops, best of 3: 13.6 usec per loop
醜いが動作します:
>>> s
'aaa12333bb445bb54b5b52'
>>> a = ''.join(filter(lambda x : x.isdigit(), s))
>>> a
'1233344554552'
>>>
list(s)
?
filter(lambda x: x.isdigit(), s)
私にとってはうまくいきました。...ああ、それは私がPython 2.7を使用しているためです。
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000ループ、ベスト3:ループあたり2.48 usec
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000ループ、ベスト3:ループあたり2.02 usec
$ python -mtimeit -s'import re; x="aaa12333bb445bb54b5b52"' 're.sub(r"\D", "", x)'
100000ループ、3つのうちの2.37ループあたり2.37 usec
$ python -mtimeit -s'import re; x="aaa12333bab445bb54b5b52"' '"".join(re.findall("[a-z]+",x))'
100000ループ、最高3:ループあたり1.97 usec
結合はサブよりも速いことを観察しました。