716 Stimmen

Wie extrahiert man Zahlen aus einer Zeichenkette in Python?

Ich möchte alle in einer Zeichenkette enthaltenen Zahlen extrahieren. Was ist für diesen Zweck besser geeignet, reguläre Ausdrücke oder die isdigit() Methode?

line = "hello 12 hi 89"

Ergebnis:

[12, 89]

4 Stimmen

Leider waren die Beispiel-Eingabedaten so simpel, dass sie zu naiven Lösungen einluden. Übliche Fälle sollten Eingabezeichenfolgen mit interessanteren Zeichen neben den Ziffern behandeln. Eine etwas anspruchsvollere Eingabe: '''gimme digits from "12", 34, '56', -789.'''

794voto

Vincent Savard Punkte 33059

Ich würde eine Regexp verwenden:

>>> import re
>>> re.findall(r'\d+', "hello 42 I'm a 32 string 30")
['42', '32', '30']

Dies entspräche auch 42 von bla42bla . Wenn Sie Zahlen nur durch Wortgrenzen (Leerzeichen, Punkt, Komma) abgrenzen wollen, können Sie \b :

>>> re.findall(r'\b\d+\b', "he33llo 42 I'm a 32 string 30")
['42', '32', '30']

Um am Ende eine Liste von Zahlen anstelle einer Liste von Zeichenfolgen zu erhalten:

>>> [int(s) for s in re.findall(r'\b\d+\b', "he33llo 42 I'm a 32 string 30")]
[42, 32, 30]

9 Stimmen

... und dann Karte int darüber und fertig. +1 besonders für den letzten Teil. Ich würde rohe Zeichenketten vorschlagen ( r'\b\d+\b' == '\\b\\d+\\b' ) allerdings.

6 Stimmen

Sie könnte in eine Liste mit einem Generator eingefügt werden, z. B.: int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]

7 Stimmen

@GreenMatt: das ist technisch gesehen ein Listenverständnis (kein Generator), aber ich würde zustimmen, dass Verständnisse/Generatoren mehr Pythonic als map .

715voto

fmark Punkte 53936

Wenn Sie nur positive ganze Zahlen extrahieren wollen, versuchen Sie Folgendes:

>>> txt = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in txt.split() if s.isdigit()]
[23, 11, 2]

Ich würde argumentieren, dass dies besser ist als das Regex-Beispiel, weil Sie kein weiteres Modul benötigen und es lesbarer ist, weil Sie nicht das Parsen (und Lernen) der Regex-Mini-Sprache .

Schwimmerwerte, negative ganze Zahlen oder ganze Zahlen im Hexadezimalformat werden nicht erkannt. Wenn Sie diese Einschränkungen nicht akzeptieren können, Antwort von jmnas unten reicht aus.

0 Stimmen

@Chris Morgan Wahr. Der Vergleich mit dem regulären Ausdruck ist allerdings nicht ganz so einfach. Ich habe die Antwort geändert, aber nicht die Zeitangaben.

11 Stimmen

Dies wird bei Fällen wie "h3110 23 cat 444.4 rabbit 11-2 dog" fehlschlagen.

11 Stimmen

Der normative Fall ist die Verwendung von re . Es ist ein allgemeines und leistungsfähiges Werkzeug (so dass Sie etwas sehr Nützliches lernen). Die Geschwindigkeit ist beim Parsen von Protokollen eher irrelevant (es handelt sich schließlich nicht um einen intensiven numerischen Solver), die re Modul ist in der Standard-Python-Bibliothek und es schadet nicht, es zu laden.

110voto

ignorance Punkte 5071

Das ist zwar etwas spät, aber man kann den Regex-Ausdruck auch auf die wissenschaftliche Schreibweise ausweiten.

import re

# Format is [(<string>, <expected output>), ...]
ss = [("apple-12.34 ba33na fanc-14.23e-2yapple+45e5+67.56E+3",
       ['-12.34', '33', '-14.23e-2', '+45e5', '+67.56E+3']),
      ('hello X42 I\'m a Y-32.35 string Z30',
       ['42', '-32.35', '30']),
      ('he33llo 42 I\'m a 32 string -30', 
       ['33', '42', '32', '-30']),
      ('h3110 23 cat 444.4 rabbit 11 2 dog', 
       ['3110', '23', '444.4', '11', '2']),
      ('hello 12 hi 89', 
       ['12', '89']),
      ('4', 
       ['4']),
      ('I like 74,600 commas not,500', 
       ['74,600', '500']),
      ('I like bad math 1+2=.001', 
       ['1', '+2', '.001'])]

for s, r in ss:
    rr = re.findall("[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?", s)
    if rr == r:
        print('GOOD')
    else:
        print('WRONG', rr, 'should be', r)

Gibt alles gut!

Außerdem können Sie sich die AWS Glue integrierte Regex

1 Stimmen

Da dies die einzige Antwort ist, die jemandem gefällt, hier eine Anleitung, wie man es mit der wissenschaftlichen Notation "[-+]? \d +[ \. ]? \d *[Ee]? \d *". Oder eine andere Variante. Viel Spaß!

0 Stimmen

Es gibt ein Problem mit dem einfachsten Fall, z. B. s = "4" liefert keine Treffer. Kann re bearbeitet werden, um auch dies zu berücksichtigen?

0 Stimmen

Eine ausführlichere Gruppe ist [+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)? Bei dieser Gruppe gibt es einige falsch-positive Ergebnisse (d.h. + wird manchmal von selbst erfasst), kann aber weitere Formen verarbeiten, wie .001 und kombiniert die Zahlen nicht automatisch (wie in s=2+1 )

106voto

dfostic Punkte 1418

Wenn Sie wissen, dass nur eine Zahl in der Zeichenkette vorkommt, d. h. 'hello 12 hi' können Sie versuchen filter .

Zum Beispiel:

In [1]: int(''.join(filter(str.isdigit, '200 grams')))
Out[1]: 200
In [2]: int(''.join(filter(str.isdigit, 'Counters: 55')))
Out[2]: 55
In [3]: int(''.join(filter(str.isdigit, 'more than 23 times')))
Out[3]: 23

Aber sei vorsichtig !!! :

In [4]: int(''.join(filter(str.isdigit, '200 grams 5')))
Out[4]: 2005

15 Stimmen

In Python 3.6.3 erhalte ich TypeError: int() argument must be a string, a bytes-like object or a number, not 'filter' - Festsetzung mit Hilfe von int("".join(filter(str.isdigit, '200 grams')))

1 Stimmen

Dies ist ein guter Ansatz, aber er funktioniert nicht, wenn wir Fließkommazahlen haben, wie 6.00 es gibt sechshundert als Antwort 600

87voto

jmnas Punkte 1054

Ich nehme an, Sie wollen Floats nicht nur ganze Zahlen, so dass ich so etwas wie diese tun würde:

l = []
for t in s.split():
    try:
        l.append(float(t))
    except ValueError:
        pass

Beachten Sie, dass einige der anderen hier geposteten Lösungen nicht mit negativen Zahlen funktionieren:

>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string -30')
['42', '32', '30']

>>> '-3'.isdigit()
False

0 Stimmen

Dies findet positive und negative Gleitkommazahlen und ganze Zahlen. Um nur positive und negative ganze Zahlen zu finden, ändern Sie float zu int .

5 Stimmen

Für negative Zahlen: re.findall("[-\d]+", "1 -2")

0 Stimmen

Macht es einen Unterschied, ob wir schreiben continue anstelle von pass in der Schleife?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X