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]
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]
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]
... 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.
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')]
@GreenMatt: das ist technisch gesehen ein Listenverständnis (kein Generator), aber ich würde zustimmen, dass Verständnisse/Generatoren mehr Pythonic als map
.
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.
@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.
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.
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
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ß!
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?
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
)
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
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')))
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
Dies findet positive und negative Gleitkommazahlen und ganze Zahlen. Um nur positive und negative ganze Zahlen zu finden, ändern Sie float
zu int
.
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.
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.'''