Antworten:
Wenn Sie nur positive Ganzzahlen extrahieren möchten, versuchen Sie Folgendes:
>>> str = "h3110 23 cat 444.4 rabbit 11 2 dog"
>>> [int(s) for s in str.split() if s.isdigit()]
[23, 11, 2]
Ich würde argumentieren, dass dies aus drei Gründen besser ist als das Regex-Beispiel. Erstens benötigen Sie kein weiteres Modul. Zweitens ist es besser lesbar, da Sie die Regex-Minisprache nicht analysieren müssen. und drittens ist es schneller (und damit wahrscheinlich pythonischer):
python -m timeit -s "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "[s for s in str.split() if s.isdigit()]"
100 loops, best of 3: 2.84 msec per loop
python -m timeit -s "import re" "str = 'h3110 23 cat 444.4 rabbit 11 2 dog' * 1000" "re.findall('\\b\\d+\\b', str)"
100 loops, best of 3: 5.66 msec per loop
Dies erkennt keine Gleitkommazahlen, negativen Ganzzahlen oder Ganzzahlen im Hexadezimalformat. Wenn Sie diese Einschränkungen nicht akzeptieren können, reicht die unten stehende Antwort von slim aus .
re
. Es ist ein allgemeines und leistungsfähiges Werkzeug (damit Sie etwas sehr Nützliches lernen). Die Geschwindigkeit spielt beim Parsen von Protokollen keine Rolle (es ist schließlich kein intensiver numerischer Löser). Das re
Modul befindet sich in der Standard-Python-Bibliothek und es tut nicht weh, es zu laden.
mumblejumble45mumblejumble
in denen ich wusste, dass es nur eine Nummer gab. Die Lösung ist einfach int(filter(str.isdigit, your_string))
.
str
die dann das str
Objekt und die Methode in Base Python überschreibt . Dies ist keine gute Vorgehensweise, da Sie sie möglicherweise später im Skript benötigen.
int(filter(...))
wird TypeError: int() argument must be a string...
für Python 3.5 ausgelöst, sodass Sie die aktualisierte Version verwenden können: int(''.join(filter(str.isdigit, your_string)))
zum Extrahieren aller Ziffern in eine Ganzzahl.
Ich würde einen regulären Ausdruck verwenden:
>>> import re
>>> re.findall(r'\d+', 'hello 42 I\'m a 32 string 30')
['42', '32', '30']
Dies würde auch 42 von entsprechen bla42bla
. Wenn Sie nur Zahlen möchten, die durch Wortgrenzen (Leerzeichen, Punkt, Komma) begrenzt sind, können Sie \ b verwenden:
>>> re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')
['42', '32', '30']
So erhalten Sie eine Liste mit Zahlen anstelle einer Liste mit Zeichenfolgen:
>>> [int(s) for s in re.findall(r'\b\d+\b', 'he33llo 42 I\'m a 32 string 30')]
[42, 32, 30]
int
und fertig. +1 speziell für den letzten Teil. Ich würde allerdings rohe Strings ( r'\b\d+\b' == '\\b\\d+\\b'
) vorschlagen .
int_list = [int(s) for s in re.findall('\\d+', 'hello 12 hi 89')]
map
.
Dies ist mehr als ein bisschen spät, aber Sie können den Regex-Ausdruck erweitern, um auch die wissenschaftliche Notation zu berücksichtigen.
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!
Darüber hinaus können Sie sich den in AWS Glue integrierten regulären Ausdruck ansehen
s = "4"
. B. gibt es keine Übereinstimmungen zurück. Kann erneut bearbeitet werden, um dies auch zu erledigen?
[+-]?\d*[\.]?\d*(?:(?:[eE])[+-]?\d+)?
Diese Gruppe gibt einige Fehlalarme aus (dh +
wird manchmal von selbst erfasst), kann jedoch mehr Formulare verarbeiten, z. B. .001
und kombiniert Zahlen nicht automatisch (wie in s=2+1
)
[-+]?[.]?[\d]+(?:,\d\d\d)*[\.]?\d*(?:[eE][-+]?\d+)?
- so dumm von mir ... wie konnte ich mir das nicht vorstellen?
Ich gehe davon aus, dass Sie Floats nicht nur ganze Zahlen wollen, also würde ich so etwas tun:
l = []
for t in s.split():
try:
l.append(float(t))
except ValueError:
pass
Beachten Sie, dass einige der anderen hier veröffentlichten 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
float
zu int
.
re.findall("[-\d]+", "1 -2")
continue
statt pass
in der Schleife schreiben ?
Wenn Sie wissen, dass es nur eine Zahl in der Zeichenfolge ist, dh "Hallo 12 Hallo", können Sie versuchen, zu filtern.
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
TypeError: int() argument must be a string, a bytes-like object or a number, not 'filter'
- es mitint("".join(filter(str.isdigit, '200 grams')))
# extract numbers from garbage string:
s = '12//n,_@#$%3.14kjlw0xdadfackvj1.6e-19&*ghn334'
newstr = ''.join((ch if ch in '0123456789.-e' else ' ') for ch in s)
listOfNumbers = [float(i) for i in newstr.split()]
print(listOfNumbers)
[12.0, 3.14, 0.0, 1.6e-19, 334.0]
Ich suchte nach einer Lösung, um die Masken von Strings zu entfernen, insbesondere von brasilianischen Telefonnummern. Dieser Beitrag wurde nicht beantwortet, hat mich aber inspiriert. Das ist meine Lösung:
>>> phone_number = '+55(11)8715-9877'
>>> ''.join([n for n in phone_number if n.isdigit()])
'551187159877'
Die Verwendung von Regex unten ist der Weg
lines = "hello 12 hi 89"
import re
output = []
#repl_str = re.compile('\d+.?\d*')
repl_str = re.compile('^\d+$')
#t = r'\d+.?\d*'
line = lines.split()
for word in line:
match = re.search(repl_str, word)
if match:
output.append(float(match.group()))
print (output)
mit findall
re.findall(r'\d+', "hello 12 hi 89")
['12', '89']
re.findall(r'\b\d+\b', "hello 12 hi 89 33F AC 777")
['12', '89', '777']
findall()
repl_str = re.compile('\d+.?\d*')
sollte sein: repl_str = re.compile('\d+\.?\d*')
Für ein reproduzierbares Beispiel mit Python3.7 re.search(re.compile(r'\d+.?\d*'), "42G").group()
'42G' re.search(re.compile(r'\d+\.?\d*'), "42G").group()
'42'
line2 = "hello 12 hi 89"
temp1 = re.findall(r'\d+', line2) # through regular expression
res2 = list(map(int, temp1))
print(res2)
Hallo ,
Sie können alle Ganzzahlen in der Zeichenfolge durch die Ziffer durchsuchen, indem Sie den Ausdruck findall verwenden.
Erstellen Sie im zweiten Schritt eine Liste res2 und fügen Sie die in der Zeichenfolge enthaltenen Ziffern zu dieser Liste hinzu
hoffe das hilft
Grüße, Diwakar Sharma
Diese Antwort enthält auch den Fall, dass die Zahl in der Zeichenfolge schwebt
def get_first_nbr_from_str(input_str):
'''
:param input_str: strings that contains digit and words
:return: the number extracted from the input_str
demo:
'ab324.23.123xyz': 324.23
'.5abc44': 0.5
'''
if not input_str and not isinstance(input_str, str):
return 0
out_number = ''
for ele in input_str:
if (ele == '.' and '.' not in out_number) or ele.isdigit():
out_number += ele
elif out_number:
break
return float(out_number)
Ich bin erstaunt zu sehen, dass noch niemand die Verwendung von erwähnt hat itertools.groupby
als Alternative erwähnt hat, um dies zu erreichen.
Sie können itertools.groupby()
zusammen mit str.isdigit()
verwenden, um Zahlen aus der Zeichenfolge zu extrahieren:
from itertools import groupby
my_str = "hello 12 hi 89"
l = [int(''.join(i)) for is_digit, i in groupby(my_str, str.isdigit) if is_digit]
Der gehaltene Wert l
ist:
[12, 89]
PS: Dies dient nur zur Veranschaulichung, um zu zeigen, dass wir als Alternative auch groupby
dies erreichen können. Dies ist jedoch keine empfohlene Lösung. Wenn Sie dies erreichen möchten, sollten Sie eine akzeptierte Antwort von fmark verwenden, die auf der Verwendung des Listenverständnisses mit str.isdigit
als Filter basiert .
Ich füge diese Antwort nur hinzu, weil niemand eine mit Ausnahmebehandlung hinzugefügt hat und weil dies auch für Floats funktioniert
a = []
line = "abcd 1234 efgh 56.78 ij"
for word in line.split():
try:
a.append(float(word))
except ValueError:
pass
print(a)
Ausgabe :
[1234.0, 56.78]
Um unterschiedliche Muster zu erfassen, ist es hilfreich, mit unterschiedlichen Mustern abzufragen.
'[\ d] + [., \ d] +'
'[\ d] * [.] [\ d] +'
'[\ d] +'
(Hinweis: Setzen Sie komplexe Muster an die erste Stelle. Andernfalls geben einfache Muster Teile des komplexen Fangs zurück, anstatt dass der komplexe Fang den vollen Fang zurückgibt.)
p = '[\d]+[.,\d]+|[\d]*[.][\d]+|[\d]+'
Im Folgenden bestätigen wir, dass ein Muster vorhanden ist re.search()
, und geben dann eine iterierbare Liste der Fänge zurück. Schließlich drucken wir jeden Fang in Klammernotation, um den Rückgabewert des Übereinstimmungsobjekts aus dem Übereinstimmungsobjekt auszuwählen.
s = 'he33llo 42 I\'m a 32 string 30 444.4 12,001'
if re.search(p, s) is not None:
for catch in re.finditer(p, s):
print(catch[0]) # catch is a match object
Kehrt zurück:
33
42
32
30
444.4
12,001
Da sich keines davon mit realen Finanzzahlen in Excel- und Word-Dokumenten befasste, die ich finden musste, ist hier meine Variation. Es verarbeitet Ints, Floats, negative Zahlen und Währungszahlen (da es beim Teilen nicht antwortet) und hat die Option, den Dezimalteil zu löschen und nur Ints zurückzugeben oder alles zurückzugeben.
Es behandelt auch das indische Laks-Zahlensystem, bei dem Kommas unregelmäßig erscheinen und nicht alle drei Zahlen voneinander entfernt sind.
Es behandelt keine wissenschaftliche Notation oder negative Zahlen in Klammern in Budgets - wird positiv erscheinen.
Es werden auch keine Daten extrahiert. Es gibt bessere Möglichkeiten, Datumsangaben in Zeichenfolgen zu finden.
import re
def find_numbers(string, ints=True):
numexp = re.compile(r'[-]?\d[\d,]*[\.]?[\d{2}]*') #optional - in front
numbers = numexp.findall(string)
numbers = [x.replace(',','') for x in numbers]
if ints is True:
return [int(x.replace(',','').split('.')[0]) for x in numbers]
else:
return numbers
@jmnas, ich mochte Ihre Antwort, aber es wurden keine Schwimmer gefunden. Ich arbeite an einem Skript zum Parsen von Code, der zu einer CNC-Fräse geht, und musste sowohl X- als auch Y-Dimensionen finden, die Ganzzahlen oder Gleitkommazahlen sein können. Deshalb habe ich Ihren Code an Folgendes angepasst. Dies findet int, float mit positiven und negativen Werten. Es werden immer noch keine hexadezimal formatierten Werte gefunden, aber Sie könnten dem num_char
Tupel "x" und "A" bis "F" hinzufügen, und ich denke, es würde Dinge wie '0x23AC' analysieren.
s = 'hello X42 I\'m a Y-32.35 string Z30'
xy = ("X", "Y")
num_char = (".", "+", "-")
l = []
tokens = s.split()
for token in tokens:
if token.startswith(xy):
num = ""
for char in token:
# print(char)
if char.isdigit() or (char in num_char):
num = num + char
try:
l.append(float(num))
except ValueError:
pass
print(l)
Die beste Option, die ich gefunden habe, ist unten. Es extrahiert eine Zahl und kann jede Art von Zeichen entfernen.
def extract_nbr(input_str):
if input_str is None or input_str == '':
return 0
out_number = ''
for ele in input_str:
if ele.isdigit():
out_number += ele
return float(out_number)
Bei Telefonnummern können Sie einfach alle nichtstelligen Zeichen mit \ D in Regex ausschließen:
import re
phone_number = '(619) 459-3635'
phone_number = re.sub(r"\D", "", phone_number)
print(phone_number)