String zerlegen

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
Nicker7
User
Beiträge: 2
Registriert: Freitag 23. September 2016, 14:02

Hallo Leute,

ich versuche gerade ein Programmzu schreiben, welches von einer Seite Daten ausließt, diese bearbeitet und dann die Resultate an eine DB sendet.
Es funktioniert eigentlich alles bloß beim heutigen Upload bin ich auf ein Programmfehler gestoßen (Menschliches Versagen muss nun mal mit eingeplant werden^^)
Ich versuche mal kurz das Problem zusammenzufassen. Es werden einige Dinge auf der Seite hochgeladen und benannt. Ich versuche die Daten auszulesen um damit das ganze zu bewerten (wie gut war welcher upload etc). Dabei gibt es folgende Regeln für den Namen:
"Bereich" : "Wert"
die einzelnen Angaben werden mit einem "_" getrennt.
Hier mal ein beispiel:

Land:Deutschland_Stadt:Berlin_Platform:Webseite (ist ausgedacht)
nun gab es aber einen Fall wo ein Schlaumeier in seinem Wert einen Unterstrich mit eingebaut hat.
Mein bisheriger Code war:

Code: Alles auswählen

def cutString( string ):
    
    array = string.split('_')
    matrix = [[0 for i in range(len(array))] for j in range(2)]
    for k in range(len(array)):
        HELP = array[k].split(':')
        matrix[0][k]=HELP[0]
        matrix[1][k]=HELP[1]
    return [matrix]
Meine idee ist es den String nun vorher zu überprüfen ob immer im wechsel "_" und ":" auftauchen. Wenn eines der Zeichen zwei mal vorkommt bevor das andere vorkommt soll es ersetzt werden (beispiel "_"="-" und ":"=";")
Eventuel fällt jemand anderes noch ein Fall ein der eintreffen kann den ich mit berücksichtigen muss.

Leider stehe ich bei der Funktion zum überprüfen etwas auf den Schauch. Ich habe es bisher mit der find() und dem Schneiden des Strings versucht aber nicht so wirklich ein Erfolg gesehen. Da dies auch bei ca 1000 Namen gemacht werden muss spielt die Performens auch eine Rolle. Da es sich theoretisch um immer den selben Ablauf handelt wäre Rekursion auch eine schöne Sache^^. Hat eventuell jemand einen Gedankenanstoß oder vll sogar schonmal soetwas ähnliches gemacht?
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Nicker7: Wo werden die Namen angegeben? Und wer hat sich denn dieses schlaue Format ausgedacht? Benutzereingaben sollten immer bei der Eingabe geprüft werden. Bei Webseiten bietet es sich an, die Werte in einem Formular einzutragen und das ganze dann als URL-Query zu kodieren. Dann sind alle Zeichen erlaubt und es gibt schon fertige Parser dafür. Alternativ kann man auch JSON benutzen. Das auf das Versagen desjenigen zu schieben, der etwas eingibt, ist frech. Versagt hat hier derjenige, der dieses Format erfunden hat.

In Python ist es unüblich eine Liste mit Dummy-Werten vorzubelegen. Was soll die zusätzliche Liste mit nur einem Element? Die natürliche Datenstruktur wäre ein Wörterbuch, oder zumindest eine Liste mit 2er-Tupeln.

Code: Alles auswählen

def parse_string(string):
    return re.findall('([^_:]+):(.*?)(?=_[^_:]+:|$)', string)
nunatak
User
Beiträge: 17
Registriert: Donnerstag 3. März 2011, 19:42

Du kannst die Teile auch eins nach dem anderen zerlegen:

Code: Alles auswählen

>>> string = 'Land:Deutschland_Stadt:Berlin_Platform:Web_seite'
>>> s = string.split('_', 1)
>>> s
['Land:Deutschland', 'Stadt:Berlin_Platform:Web_seite']
>>>
Und dann immer im Wechsel nach _ dann nach : teilen, bis alle Teile durch sind.
Nicker7
User
Beiträge: 2
Registriert: Freitag 23. September 2016, 14:02

Vielen Dank für die schnelle Antwort,

ob die Seite professionell ist, steht leider nicht zur debatte. Bin auch der Meinung dass vorher überprüft werden sollte ob die Eingabe richtig ist. Mein Chef möchte aber von der Seite die Daten haben und ich möchte nicht den ganzen Tag verbringen die per Hand in eine Excel Datei zu kopieren. Hat auch bisher gut geklappt..................Ist ja auch nicht weiter wichtig.
Ich dachte nicht dass es wichtig ist aber ich ziehe die Daten nicht über das auslesen der HTML sondern über JSON.
@nunatak
ach das wusste ich garnicht. Hätte mir mal die Funktion vorher genauer angucken sollen^^. Aber das ist ein sehr guter Hinweis.
Dann würde ich das so lösen dass ich der Reihe nach den String splitte, im Teilstück überprüfe ob ein : vorhanden ist, wenn nicht gehe ich ein "_" weiter.
Nur noch die Frage wann ich damit aufhöre. for bietet sich nicht an da ich kein Ende kenne. while könnte ich nehmen solange kein Fehler auftritt. Aber was wäre dann meine Abbruchbedingung?
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Schau dir mal an, wie lang die Liste ist, wenn kein Trenner enthalten war. Genau dies kannst du als Abbruchbedingung nutzen.

Alternativ könntest du auch jedes Mal testen, ob der Trenner enthalten ist und nur dann splitten. Das finde ich noch naheliegender. Es ist aber von der Performance nicht so gut, weil dann eine zusätzliche Suchoperation ausgeführt wird, die ja eigentlich schon durch `split()` übernommen wird. Das Testen auf die Länge macht intern viel weniger Aufwand.

Wir sprechen hier natürlich von theoretischen Überlegungen. In der Praxis kann es gut sein, dass der Gesamteffekt sich nicht spürbar verändert, egal ob Methode 1 oder 2 genutzt wird.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@nunatak: das Problem von Nicker7 ist ja, dass im Wert Unterstriche vorkommen können. Man müßte also von Rechts anfangen und nach dem letzten ':' suchen. Zu Ende ist man, wenn der Reststring kein '_' mehr enthält.

@Nicker7: wenn Du schon JSON benutzt, warum dann noch diese komische Kodierung? Übrigens, der reguläre Ausdruck in meinem ersten Post löst auch Dein Problem.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Land:Deutschland_Stadt:Berlin_Platform:Webseite
Wenn das wirklich die Eingabe ist, die von einem Benutzer verlangt wird, dann ist das so was "broken by design", da hat Sirius3 völlig recht.
Mach' einfach drei Felder draus und gut ist.

Und wenn ihr euren "broken-by-design" wirklich weiter verfolgen wollt, dann würde ich schon client-seitig prüfen, ob die Eingabe im Feld genau zwei Underscores und drei Doppelpunkte enthält. Zusätzlich zur server-seitigen Validierung.

Gruß, noisefloor
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Achja, wenn man vorab die Trenner mittels `count()` zählt, dann hätte man auch ein Argument für eine `for`-Schleife.
Antworten