Entfernen aller nicht numerischen Zeichen aus der Zeichenfolge in Python


Antworten:


266
>>> import re
>>> re.sub("[^0-9]", "", "sdkjh987978asd098as0980a98sd")
'987978098098098'

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.


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

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'

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

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

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.