回答:
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'
これが最も効率的な方法かどうかはわかりませんが、次のようになります。
>>> ''.join(c for c in "abc123def456" if c.isdigit())
'123456'
''.join
一部には、その間の任意の文字をせずに一緒にすべての結果の文字を組み合わせることを意味します。次に、残りはリスト内包表記であり、(おそらく推測できるように)条件に一致する文字列の部分のみを取得しますisdigit
。
ミックスに別のオプションを追加するためだけに、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'
このような削除操作を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文字列で、使用する方が簡単かもしれないTAD単純:
>>> unondig = dict.fromkeys(xrange(65536))
>>> for x in string.digits: del unondig[ord(x)]
...
>>> s = u'abc123def456'
>>> s.translate(unondig)
u'123456'
特に、Unicode文字列に非常に高いord値の文字が含まれている可能性がある場合(dictが過度に大きくなるため、;-)、実際のdictではなくマッピングクラスを使用することをお勧めします。例えば:
>>> 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'
>>>
(sys.maxunicode - number_of_non_numeric_chars)
エントリが「含まれる可能性がある」ため、dictは無条件に「過度に大きい」。(3)string.digitsが十分ではなく、Unicodedataモジュールを解読する必要があるかどうかを検討します(4)単純化および潜在的可能性のためにre.sub(r '(?u)\ D +'、u ''、text)を検討します速度。