Entfernen aller nicht numerischen Zeichen aus der Zeichenfolge in Python

Antworten:

266
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'
Ned Batchelder
quelle
89
das könnte re sein (r "\ D", "", "sdkjh987978asd098as0980a98sd")
newacct
2
und das könnte sein: von re import sub
James Koss
88

Ich bin mir nicht sicher, ob dies der effizienteste Weg ist, aber:

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

Der ''.joinTeil bedeutet, alle resultierenden Zeichen ohne dazwischen liegende Zeichen miteinander zu kombinieren. Dann ist der Rest ein Listenverständnis, bei dem wir (wie Sie wahrscheinlich erraten können) nur die Teile der Zeichenfolge nehmen, die der Bedingung entsprechen isdigit.

Mark Rushakoff
quelle
1
Das macht das Gegenteil. Ich denke du meinst "nicht c.isdigit ()"
Ryan R. Rosario
7
Entfernen Sie alle nicht numerischen == behalten Sie nur numerische.
Mark Rushakoff
10
Ich finde es gut, dass für diesen Ansatz für diese einfache Funktion kein erneutes Einziehen erforderlich ist.
Triunenature
Beachten Sie, dass diese Lösung im Gegensatz zu Implementierungen mit str.translate sowohl in Python 2.7 als auch in 3.4 funktioniert. Danke dir!
Alex
1
Ich bevorzuge diese Alternative. Die Verwendung eines regulären Ausdrucks scheint mir übertrieben.
Alfredocambera
18

Dies sollte sowohl für Zeichenfolgen als auch für Unicode-Objekte in Python2 und für Zeichenfolgen und Bytes in Python3 funktionieren:

# 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))
tzot
quelle
9

Um der Mischung eine weitere Option hinzuzufügen, gibt es im stringModul mehrere nützliche Konstanten . In anderen Fällen sind sie zwar nützlicher, können aber hier verwendet werden.

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

Das Modul enthält mehrere Konstanten, darunter:

  • ascii_letters (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)
  • hexdigits (0123456789abcdefABCDEF)

Wenn Sie diese Konstanten häufig verwenden, kann es sich lohnen, sie in a umzuwandeln frozenset. Dies ermöglicht O (1) -Suchen anstelle von O (n), wobei n die Länge der Konstante für die ursprünglichen Zeichenfolgen ist.

>>> digits = frozenset(digits)
>>> ''.join(c for c in "abc123def456" if c in digits)
'123456'
Tim McNamara
quelle
'' .join (c für c in "abc123def456", wenn c.isdigit ()) funktioniert in meinem Python 3.4
Eino Mäkitalo
7

@Ned Batchelder und @newacct lieferten die richtige Antwort, aber ...

Nur für den Fall, dass Ihre Zeichenfolge Komma (,) dezimal (.) Enthält:

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

Der schnellste Ansatz, wenn Sie mehr als nur ein oder zwei solcher Entfernungsvorgänge ausführen müssen (oder sogar nur einen, aber an einer sehr langen Zeichenfolge! -), besteht darin, sich auf die translateMethode der Zeichenfolgen zu verlassen, obwohl einige Vorbereitungen erforderlich sind:

>>> 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'

Die translateMethode ist bei Unicode-Zeichenfolgen anders und möglicherweise etwas einfacher zu verwenden als bei Byte-Zeichenfolgen, übrigens:

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

Möglicherweise möchten Sie eine Zuordnungsklasse anstelle eines tatsächlichen Diktats verwenden, insbesondere wenn Ihre Unicode-Zeichenfolge möglicherweise Zeichen mit sehr hohen Ordnungswerten enthält (dies würde das Diktat übermäßig groß machen ;-). Beispielsweise:

>>> 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'
>>> 
Alex Martelli
quelle
2
(1) Magische Zahlen nicht hart codieren; s / 65536 / sys.maxunicode / (2) Das Diktat ist bedingungslos "übermäßig groß", da die Eingabe "möglicherweise" (sys.maxunicode - number_of_non_numeric_chars)Einträge enthalten kann . (3) Überlegen Sie, ob string.digits möglicherweise nicht ausreichen, was dazu führt, dass das Unicodedata-Modul aufgebrochen werden muss. (4) Überlegen Sie der Einfachheit und dem Potenzial nach re (r '(? U) \ D +', u '', Text) Geschwindigkeit.
John Machin
2

Viele richtige Antworten, aber falls Sie es direkt in einem Float möchten, ohne Regex zu verwenden:

x= '$123.45M'

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

123,45

Sie können den Punkt für ein Komma je nach Ihren Anforderungen ändern.

Ändern Sie dies, wenn Sie wissen, dass Ihre Nummer eine Ganzzahl ist

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

1123

Alberto Ibarra
quelle