Hi,
ich habe eine Liste im Format von [aa, bb, cc] (aus einer anderen Quelle). Natürlich ist diese keine gültige Zeichenketten-Liste in Python wie ["aa", "bb", "cc"], aber gibt’s Methode, die sowas umwandelt?
Zeichenketten Umwandlung
- __blackjack__
- User
- Beiträge: 14431
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@senmeis: Wenn es ein gängiges Standardformat ist, gibt es ziemlich wahrscheinlich etwas fertiges, ansonsten muss man sich das halt schreiben. Dafür sollte man wissen wie das Format formal aufgebaut ist. In einfachen Fällen kann man das mit den Grundlegenden Zeichenkettenoperationen machen. Eventuell helfen reguläre Ausdrücke. Oder man benutzt eine Bibliothek wie PyParsing.
“Design patterns are kind of like sarcasm: hard to use well, not always appropriate,
and disgustingly bad when applied to problems they are not meant to solve.” — ajones in c.l.python
and disgustingly bad when applied to problems they are not meant to solve.” — ajones in c.l.python
- noisefloor
- User
- Beiträge: 4337
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
die Liste muss dann als Text vorliegen. Das kann man dann von Hand in kleinen Schritten machen:
Je nach dem, wie die echten Daten aussehen, kann man das ggf. auch noch kompakter Schreiben.
Wo kommen die Daten den her? Es spricht einiges dafür, dass schon beim Lesen der Daten was falsch gemacht wurde, z.B. JSON in platten Text zu wandeln.
Gruß, noisefloor
die Liste muss dann als Text vorliegen. Das kann man dann von Hand in kleinen Schritten machen:
Code: Alles auswählen
>>> zeichenkette = '[aa, bb, cc]'
>>> zeichenkette = zeichenkette[1:-1]
>>> zeichenkette
'aa, bb, cc'
>>> daten = zeichenkette.split(',')
>>> daten
['aa', ' bb', ' cc']
>>> daten = [d.strip() for d in daten]
>>> daten
['aa', 'bb', 'cc']Wo kommen die Daten den her? Es spricht einiges dafür, dass schon beim Lesen der Daten was falsch gemacht wurde, z.B. JSON in platten Text zu wandeln.
Gruß, noisefloor
Oder alternativ dazu der reguläre Ausdruck mit re.split():
\s = (White-)Space, d. h. neben Leerzeichen auch Tabs (\t) und Zeilentrenner (Newline, \n)
* = beliebig viele Vorkommen, wobei auch kein Vorkommen zählt
Man sagst Python somit: "Trenne an jedem Komma gefolgt von einer beliebigen Anzahl an Whitespace"
Das funktioniert grob wie das Beispiel von noisefloor, würde aber Leerraum stehen lassen, der NICHT direkt auf ein Komma folgt.
Das hier wäre übrigens das vollwertige Regex-Äquivalent zum Code von noisefloor:
Unbedingt lesbarer ist das natürlich nicht. Man muss auch bei der Gruppierung aufpassen, damit re.findall() wie gewünscht funktioniert. Dazu die Doku von re.findall():
Naja, es funktioniert, aber ist sicherlich nicht für jeden die ideale Lösung, sag ich mal.
Code: Alles auswählen
>>> s = "[aa,bb, cc,\ndd,\tee]"
>>> re.split(r",\s*", s[1:-1])
['aa', 'bb', 'cc', 'dd', 'ee']* = beliebig viele Vorkommen, wobei auch kein Vorkommen zählt
Man sagst Python somit: "Trenne an jedem Komma gefolgt von einer beliebigen Anzahl an Whitespace"
Das funktioniert grob wie das Beispiel von noisefloor, würde aber Leerraum stehen lassen, der NICHT direkt auf ein Komma folgt.
Das hier wäre übrigens das vollwertige Regex-Äquivalent zum Code von noisefloor:
Code: Alles auswählen
>>> re.findall(r"(\S+?),\s*", s[1:-1])
['aa', 'bb', 'cc', 'dd']\S ist das Gegenteil von \s, somit trifft das auf alles zu, was KEIN Whitespace ist. Das Plus heißt mindestens ein Vorkommen (hier also mindestens ein Zeichen druckbarer Text). In Verbindung mit dem Fragezeichen geht die Engine in den non-greedy Modus, damit das Komma (welches ja auch non-Whitespace ist) nicht Teil des Treffers wird.The result depends on the number of capturing groups in the pattern. If there are no groups, return a list of strings matching the whole pattern. If there is exactly one group, return a list of strings matching that group. If multiple groups are present, return a list of tuples of strings matching the groups. Non-capturing groups do not affect the form of the result.
Naja, es funktioniert, aber ist sicherlich nicht für jeden die ideale Lösung, sag ich mal.
Upsi, mein Code verschluckt leider das letzte Element.
Ich habe die KI befragt und heraus kam eine deutlich robustere Variante:
Er definiert in den eckigen Klammern eine eigene Zeichenklasse. Achtung: Dies bezieht sich noch nicht auf die eckigen Klammern unseres Beispieltextes.
Durch das vorangestellte ^-Zeichen kehrt er die Logik um und sagt also: Suche alle Zeichen AUSSER Komma, Whitespace, eckige öffnende Klammer und eckige schließende Klammer. Der Backslash vor der eckigen schließenden Klammer maskiert das Zeichen. Erst im direkten Anschluss nimmt er sie, um die eigentliche Definition der Zeichenklasse zu beenden. Und davon halt mindestens ein Vorkommen (+), d. h. meine Treffer sind alle Zeichenfolgen, die keine der "verbotenen" Zeichen enthalten. Findet er Zeichen aus der negierten Klasse, ignoriert er sie und erstellt den nächsten Treffer ab einem erlaubten Zeichen. Ist doch ganz einfach, oder?
Im Hinblick auf die Performance ist übrigens die Anwendung der Schleife deutlich besser. Reguläre Ausdrücke sind oftmals nur eine Art "akademische Übung", um sie selber ein bisschen besser zu verstehen. Manchmal können sie sinnvoll sein, aber oft sind sie das eben auch nicht.
Ich habe die KI befragt und heraus kam eine deutlich robustere Variante:
Code: Alles auswählen
>>> s = '[\n\taa,bb, cc,\ndd,\tee ,ff,]'
>>> re.findall(r'[^,\s[\]]+', s)
['aa', 'bb', 'cc', 'dd', 'ee', 'ff']Durch das vorangestellte ^-Zeichen kehrt er die Logik um und sagt also: Suche alle Zeichen AUSSER Komma, Whitespace, eckige öffnende Klammer und eckige schließende Klammer. Der Backslash vor der eckigen schließenden Klammer maskiert das Zeichen. Erst im direkten Anschluss nimmt er sie, um die eigentliche Definition der Zeichenklasse zu beenden. Und davon halt mindestens ein Vorkommen (+), d. h. meine Treffer sind alle Zeichenfolgen, die keine der "verbotenen" Zeichen enthalten. Findet er Zeichen aus der negierten Klasse, ignoriert er sie und erstellt den nächsten Treffer ab einem erlaubten Zeichen. Ist doch ganz einfach, oder?
Im Hinblick auf die Performance ist übrigens die Anwendung der Schleife deutlich besser. Reguläre Ausdrücke sind oftmals nur eine Art "akademische Übung", um sie selber ein bisschen besser zu verstehen. Manchmal können sie sinnvoll sein, aber oft sind sie das eben auch nicht.
Falls es in Wirklichkeit verschachtelte Listen sind, könnte man auch das bereits vorgeschlagene PyParsing-Modul verwenden.
Der folgende Code samt Kommentare stammt aus meinem Dialog mit der Google KI:
Ich wollte, dass auch Kommas am Ende erlaubt sind, da solche Listen in Python auch funktionieren.
Der folgende Code samt Kommentare stammt aus meinem Dialog mit der Google KI:
Code: Alles auswählen
import pyparsing as pp
# Test-String mit tiefer Verschachtelung und Trailing-Commas auf verschiedenen Ebenen
s = '[ aa, [bb, 123,], cc, [\n dd, [ \t ee, ff, ] , ], ]'
# 1. Platzhalter für den Ausdruck definieren, da er sich gleich selbst referenziert
liste = pp.Forward()
# 2. Was darf in einer Liste stehen? Entweder ein normales Wort/Zahl ODER eine weitere Liste
element = pp.Word(pp.alphanums) | liste
# 3. Den Platzhalter mit der echten Grammatik füllen (dein bewährter Ansatz!)
liste <<= pp.Suppress("[") + pp.DelimitedList(element, allow_trailing_delim=True) + pp.Suppress("]")
# Parser ausführen
ergebnis = liste.parse_string(s)
# .as_list() wandelt das PyParsing-Ergebnis in eine echte, verschachtelte Python-Liste um
print(ergebnis.as_list())
# Ausgabe: ['aa', ['bb', '123'], 'cc', ['dd', ['ee', 'ff']]]
-
Pedroski55
- User
- Beiträge: 63
- Registriert: Freitag 25. Juli 2025, 00:20
Falls du
liste = [aa, bb, cc]
auswerten willst, kommt gleich die Meldung: NameError: name 'aa' is not defined. Watn dat?
Die hexadecimale Hexe mit den Büsten dezimalisiert:
liste = [aa, bb, cc]
auswerten willst, kommt gleich die Meldung: NameError: name 'aa' is not defined. Watn dat?
Die hexadecimale Hexe mit den Büsten dezimalisiert:
Code: Alles auswählen
Büstengrößen = 'aa, bb, cc,dd'
Büstengrößen_liste = Büstengrößen.split(',')
for B in Büstengrößen_liste:
print(int(B, 16))Hüte dich!170
187
204
221
Tja, es geht halt um den Input aus einer externen Quelle, der logischerweise als String vorliegt. Ziel ist es, diesen Input in eine "Python-Form" zu bekommen, damit es eben keinen NameError gibt. Wenn man den Thread aufmerksam liest und versteht, dann sollte dies einem klar sein und deine Frage somit gar nicht aufkommen...Pedroski55 hat geschrieben: Donnerstag 20. August 2026, 07:54 Falls du
liste = [aa, bb, cc]
auswerten willst, kommt gleich die Meldung: NameError: name 'aa' is not defined. Watn dat?
Übrigens hat die KI mich mal wieder belogen und betrogen, denn der Code aus meinem letzten Beitrag hat bloß eine flache Liste erzeugt.
Das hier funktioniert aber tatsächlich:
Das hier funktioniert aber tatsächlich:
Code: Alles auswählen
import pyparsing as pp
# Test-String mit verschiedenen Anführungszeichen und Leerzeichen darin
source = '[ aa, "Hallo Welt", [bb, \'einfache quotes\', 123,], cc, ]'
sequence = pp.Forward()
# Ein String kann in "..." oder in '...' stehen
quoted_string = pp.QuotedString('"') | pp.QuotedString("'")
# Ein Element ist nun: ein normales Wort/Zahl ODER ein Quoted-String ODER eine Unterliste
element = pp.Word(pp.alphanums) | quoted_string | pp.Group(sequence)
sequence <<= pp.Suppress("[") + pp.DelimitedList(element, allow_trailing_delim=True) + pp.Suppress("]")
ergebnis = sequence.parse_string(source)
print(ergebnis.as_list())
# Ausgabe: ['aa', 'Hallo Welt', ['bb', 'einfache quotes', '123'], 'cc']