Zeichenketten Umwandlung

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
senmeis
User
Beiträge: 9
Registriert: Montag 7. Juli 2025, 14:20

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?
Benutzeravatar
__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
Benutzeravatar
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:

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']
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
Benutzeravatar
snafu
User
Beiträge: 7000
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Oder alternativ dazu der reguläre Ausdruck mit re.split():

Code: Alles auswählen

>>> s = "[aa,bb,    cc,\ndd,\tee]"
>>> re.split(r",\s*", s[1:-1])
['aa', 'bb', 'cc', 'dd', 'ee']
\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:

Code: Alles auswählen

>>> re.findall(r"(\S+?),\s*", s[1:-1])
['aa', 'bb', 'cc', 'dd']
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():
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.
\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.

Naja, es funktioniert, aber ist sicherlich nicht für jeden die ideale Lösung, sag ich mal. :)
Benutzeravatar
snafu
User
Beiträge: 7000
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Upsi, mein Code verschluckt leider das letzte Element. :oops:

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']
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.
Benutzeravatar
snafu
User
Beiträge: 7000
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

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:

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']]]
Ich wollte, dass auch Kommas am Ende erlaubt sind, da solche Listen in Python auch funktionieren.
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:

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))
170
187
204
221
Hüte dich!
Antworten