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


回答:



89

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

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

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


1
それは反対です。「c.isdigit()ではない」という意味だと思います
ライアンR.ロサリオ

7
すべての非数値を削除==数値のみを保持。
マークルシャコフ2009

10
この単純な関数のために、このアプローチではreをプルする必要がないことが好きです。
triunenature

str.translateを使用した実装とは異なり、このソリューションはPython 2.7と3.4の両方で機能することに注意してください。ありがとうございました!
Alex

1
私はこの代替案を好む。正規表現を使用することは私にはやり過ぎに思えます。
alfredocambera

18

これは、Python2では文字列とUnicodeオブジェクトの両方で機能し、Python3では文字列とバイトの両方で機能するはずです。

# 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))

9

ミックスに別のオプションを追加するためだけに、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'

'' .join(c for c.isdigit()が "abc123def456"のcに対してc)は、私のpython 3.4で動作します
EinoMäkitalo

7

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

文字列にコンマ(、)、デシマル(。)がある場合に備えて:

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

5

このような削除操作を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'
>>> 

2
(1)マジックナンバーをハードコーディングしないでください。s / 65536 / sys.maxunicode /(2)入力に(sys.maxunicode - number_of_non_numeric_chars)エントリが「含まれる可能性がある」ため、dictは無条件に「過度に大きい」。(3)string.digitsが十分ではなく、Unicodedataモジュールを解読する必要があるかどうかを検討します(4)単純化および潜在的可能性のためにre.sub(r '(?u)\ D +'、u ''、text)を検討します速度。
ジョン・マチン

2

多くの正解ですが、正規表現を使用せずに、フロートで直接必要な場合:

x= '$123.45M'

float(''.join(c for c in x if (c.isdigit() or c =='.'))

123.45

必要に応じて、コンマのポイントを変更できます。

数値が整数であることがわかっている場合は、これを変更します

x='$1123'    
int(''.join(c for c in x if c.isdigit())

1123

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.