web-dev-qa-db-ja.com

Pythonの文字列からすべての非数値文字を削除します

Pythonで文字列からすべての非数値文字を削除するにはどうすればよいですか?

120
grizzley
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'
226
Ned Batchelder

これが最も効率的な方法かどうかはわかりませんが、次のとおりです。

>>> ''.join(c for c in "abc123def456" if c.isdigit())
'123456'

''.join部分は、結果のすべての文字を、間に文字を入れずに結合することを意味します。それから残りはリストの内包です。ここでは(おそらく推測できるように)条件isdigitに一致する文字列の部分のみを取得します。

76
Mark Rushakoff

これは文字列とUnicodeオブジェクトに対して機能するはずです:

# python <3.0
def only_numerics(seq):
    return filter(type(seq).isdigit, seq)

# python ≥3.0
def only_numerics(seq):
    seq_type= type(seq)
    return seq_type().join(filter(seq_type.isdigit, seq))
13
tzot

別のオプションをミックスに追加するために、stringモジュール内にいくつかの便利な定数があります。他のケースではより便利ですが、ここで使用できます。

>>> from string import digits
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'

モジュールには、次のようないくつかの定数があります。

  • ascii_letters(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits(0123456789abcdefABCDEF)

これらの定数を頻繁に使用している場合は、frozensetに変換する価値があります。これにより、O(n)ではなくO(1)ルックアップが有効になります。nは元の文字列の定数の長さです。

>>> digits = frozenset(digits)
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'
6
Tim McNamara

このような削除操作を1つまたは2つ以上(または1つだけでも非常に長い文字列で!)実行する必要がある場合、最速のアプローチは、文字列のtranslateメソッドに依存することです準備が必要です:

>>> import string
>>> allchars = ''.join(chr(i) for i in xrange(256))
>>> identity = string.maketrans('', '')
>>> nondigits = allchars.translate(identity, string.digits)
>>> s = 'abc123def456'
>>> s.translate(identity, nondigits)
'123456'

translateメソッドは異なりますが、バイト文字列よりもUnicode文字列で使用する方が簡単です。

>>> unondig = dict.fromkeys(xrange(65536))
>>> for x in string.digits: del unondig[ord(x)]
... 
>>> s = u'abc123def456'
>>> s.translate(unondig)
u'123456'

特に、Unicode文字列に非常に高いord値を持つ文字が含まれる可能性がある場合は、実際の辞書ではなくマッピングクラスを使用することをお勧めします(辞書が非常に大きくなります;-)。例えば:

>>> class keeponly(object):
...   def __init__(self, keep): 
...     self.keep = set(ord(c) for c in keep)
...   def __getitem__(self, key):
...     if key in self.keep:
...       return key
...     return None
... 
>>> s.translate(keeponly(string.digits))
u'123456'
>>> 
5
Alex Martelli

@Ned Batchelderと@newacctは正しい答えを提供しましたが、...

文字列にカンマ(、)十進数(。)がある場合に備えて:

import re
re.sub("[^\d\.]", "", "$1,999,888.77")
'1999888.77'
1
kennyut