Zeichenextraktion via split

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
stielchen
User
Beiträge: 14
Registriert: Sonntag 27. Juli 2014, 09:28

Hallo zusammen,
ich möchte aus einem String mit dem Format "n1.n2.n3!n4" die ersten 3 Zahlen (n1-n3) in ein Dictionary ausgeben.
"n1", "n2", "n3" und "n4" sind dabei "beliebig" lange Ganzahlen, "!" ist ein einzelnes, beliebiges Zeichen.

Z. B. wäre bei "4.3.20r40349" das Ergebnis ['4', '3', '20'], ein weiteres Beispiel:
"42.222.23445_3487", hier sollte in der Liste ['42', '222', '23445'] stehen.

Mit der "split".Methode und einem bekannten Zeichen (z.B. 'r') funktioniert das wie folgt alles wunderbar, es könnte nun aber sein, dass der Begrenzer kein 'r', sondern ein beliebiges anderes, mir nicht bekanntes, Zeichen ist.

Code: Alles auswählen

txt="4.3.20r40349"
return {
    'major' : int(txt.split('r')[0].split('.')[0]),
    'minor' : int(txt.split('r')[0].split('.')[1]),
    'patch' : int(txt.split('r')[0].split('.')[2])
}
Hat jemand evtl. eine Idee, wie man möglichst einfach die ersten 3 Zahlen aus einem String extrahieren kann? Sicher könnte ich mir jetzt irgendwas zusammenmurksen, aber hat evtl. jemand eine handliche Idee wie man aus so einem Stringformat umgeht?

Danke Euch
stielchen
BlackJack

@stielchen: Schau Dir mal das `re`-Modul an. Und bitte lass den armen Rechner nicht unnötig mehrfach die gleiche Arbeit verrichten. Das Ergebnis von ``txt.split('r')[0].split('.')`` in Deinem Beispiel ist jedes mal das selbe, das braucht man deshalb nicht dreimal machen — einmal reicht.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@stielchen
``re.split`` kann dafür eine Lösung sein:

Code: Alles auswählen

>>> import re
>>> re.split(r'\D', '42.222.23445_3487')[:3]
['42', '222', '23445']
>>> re.split(r'\D', '4.3.20r40349')[:3]
['4', '3', '20']
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@mutetella: wenn man schon so ein schönes Pattern hat, sollte man das auch nutzen :wink:

Code: Alles auswählen

import re

def split_version(text):
    return re.match(r'(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)', text).groupdict()
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@Sirius3
Already again what learned... :mrgreen:

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
stielchen
User
Beiträge: 14
Registriert: Sonntag 27. Juli 2014, 09:28

@BlackJack:
Oh, natürlich. Das war der Fleiß des Ahnungslosen...
Stimmt, das re-Modul mit den regulären Ausdrücken hatte ich mir auch mal angeschaut und bin da gescheitert und hielt es für oversized für mein Vorhaben. Wenn ich ehrlich bin, kam ich mit meinen Versuchen auch nicht wirklich weiter.

@mutella:
Aaah, das sieht doch schon super aus, Danke Dir!

@Sirius:
Tränen der Ergriffenheit kullern über meine Wange. Das ist ja super, ebenfalls vielen Dank.
Hab in meiner Anfrage nur einen kleinen Fehler gemacht und eine Liste erwähnt, die Ausgabe sollte, aber eigentlich so sein:
{'major': 4, 'minor': 3, 'patch': 20} (also Integer-Werte) statt Strings wie im Ergebnis Deines tollen Code-Beispiels:
{'major': '4', 'minor': '3', 'patch': '20'}

Bis dato habe ich die regulären Ausdrücke bzw. die Anwendung des re-Moduls noch nicht verstanden, daher weiß ich nicht, wie man das Dictionary mit Integer-Werten erstellt. Geht doch wahrscheinlich auch?

Grüße
stielchen
Antworten