Liste in einem String erkennen

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
mampfgnom
User
Beiträge: 8
Registriert: Mittwoch 6. Juni 2012, 10:10

Hallo.

Ich bin Python Neuling und stehe vor einem kleinen Problem beim Einlesen einer Datei. Das Einlesen der Zeilen ist kein Problem allerdings muss ich die jeweilige Zeile aufteilen und Variablen zuweisen und da klemmt es ein bisschen. Hier ein Beispiel:

Code: Alles auswählen

s = '1, 2, 3, [12, 13,14]'
Ich will diesen String jetzt gerne so aufteilen dass ich 3 Integer Variablen erhalte und eine Liste. Bisher kannte ich nur das Vorgehen.

Code: Alles auswählen

var1,var2,var3,var4 = s.strip(' ').split(',')
Das ist aber ein naiver Versuch den hinteren Teil in den eckigen Klammern in eine einzige Variable zu speichern. Nach ein wenig Recherche habe ich mir das hier zusammen gebastelt:

Code: Alles auswählen

links = s.rfind('[')
rechts = s.rfind(']')
liste = s[links+1:rechts].split(',')
for i in range(len(liste)):
	liste[i] = int(liste[i])
var1, var2, var3 = s[:links-1].strip(' ').split(',')
Das scheint auch zu funktionieren. Ich weiß nur nicht, ob das allgemeingültig und stabil ist. Kennt ihr vielleicht eine bessere Lösung oder ist das hier schon okay?

Grüße

Mampfgnom

P.S.: Ich hoffe das ist das richtige Forum
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Man könnte es so machen:

Code: Alles auswählen

import json
a, b, c, d = (item for item in json.loads('[%s]' % '1, 2, 3, [12, 13,14]'))
print(a, b, c, d)
:mrgreen:

Aber mal im Ernst: Woher stammen denn diese Daten? Evtl. kann man das Format wirklich *direkt* auf JSON (o.ä.) umstellen? Das erschiene mir sinnvoller. Wenn nicht, ist das irgend ein anderes Standardformat? Wenn ja, gibt es dafür ggf. schon einen eigenen Parser?

Wenn das alles nicht geht, dann braucht man def. einen Gesamtüberblick über die Grammatik des ganzen. Dann kann man einen robusten Parser dafür schreiben.

Aber noch etwas: Wozu willst Du die Werte an separate Namen binden? Evtl. ist das an sich schon unnötig. Aber ohne den Kontext kann man dazu wenig sagen...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
mampfgnom
User
Beiträge: 8
Registriert: Mittwoch 6. Juni 2012, 10:10

Hallo und Danke für die Antwort.

Du hast mich ehrlich gesagt ein wenig erschlagen mit deiner Antwort, wie gesagt ich bin Neuling. Ich versuche mal deine Fragen zu beantworten:

Die Daten stammen von mir selber und entstehen im Laufe eines Rechenzyklus. Das Format ist fest und lautet:

int, int, int, list

Die Anzahl der Elemente in der Liste variiert allerdings. Ich denke einen eigenen Parser brauch man dafür nicht. Deine Variante sieht sehr schön kompakt aus, allerdings habe ich nur Python 2.4.3.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wenn die Daten von Dir selber stammen, dann wähle doch für das Serialisieren bereits ein gescheites Format! JSON fiel mir jetzt schnell ein, es gibt ja noch zig anderen, die gingen. Für 2.4 muss man iirc das `simplejson`-Modul nachinstallieren, da dieses dann erst ab 2.5 als Modul in die Standard-Lib aufgenommen wurde.

Darf man fragen, wieso Du mit so einer alten Version von Python arbeitest? Wenn es keine zwingenden Gründe gibt, steig auf jeden Fall auf die aktuelle 2.7er um!

Du kannst auch mal gucken, ob Dir `pickle` reichen würde. Wenn Du die Datei nicht extern lesen / schreiben willst, ginge das sicherlich auch.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Wozu ist der Generatorausdruck gut?

Code: Alles auswählen

In [215]: json.loads('[%s]' % '1, 2, 3, [12, 13,14]')
Out[215]: [1, 2, 3, [12, 13, 14]]

In [216]: a, b, c, d = json.loads('[%s]' % '1, 2, 3, [12, 13,14]')

In [217]: a
Out[217]: 1

In [218]: b
Out[218]: 2

In [219]: c
Out[219]: 3

In [220]: d
Out[220]: [12, 13, 14]
mampfgnom
User
Beiträge: 8
Registriert: Mittwoch 6. Juni 2012, 10:10

Ich arbeite in der Universität an meiner Diplomarbeit und auf dem Rechner, der mir zu Verfügung gestellt wird, ist nur das alte Python installiert. Ich werde aber mal beim Systemadministrator anfragen, ob ich die neue Version aufgespielt kriegen kann.
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Na gut, Fremdrechner / Systemadministrator könnte schon zu "zwingenden Gründen" gegen ein Update der Pythonversion zählen. Gibt es aber auch zwingende Gründe, wieso du die Daten unbedingt in dieser Form speicherst? Dadurch entstehen ja erst die Probleme beim Wieder-Einlesen. Wenn du tatsächlich beide Seiten dieser deiner dann ja internen Schnittstelle beeinflussen kannst, dann würde ich die anderen unterstützen, und nicht mehr viel Zeit mit String-Manipulationen vertrödeln, sondern direkt ein vernünftige Format wählen. Schnittstellen nerven, sollte man vermeiden. :mrgreen:
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben:@Hyperion: Wozu ist der Generatorausdruck gut?
Äh... der sah so schnuckelig aus :oops: Man sollte Dinge niemals so schnell posten, wenn man erst eine andere Idee hatte... ich hoffe die Ausrede reicht :-)

@Kebap: Ich hoffe der OP hat verstanden, dass er auch schon beim *Serialisieren* auf eine entsprechende Lib zurückgreifen soll ;-) Bei `pickle` hätte ich Magenschmerzen, dass das Erzeugte mit einem neueren Python nicht mehr gelesen werden kann - oder irre ich hier? Was bleibt sonst so? `shelve`, `marshall`? JSON erscheint mit von der Struktur her erst einmal am natürlichsten.

Man kann aufgrund der Unerfahrenheit des OP natürlich generell mal nachfragen, ob eine Serialisierung wirklich erforderlich ist...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Pickles sind über Python-Versionen hinweg lesbar (zumindest rückwärtskompatibel). Das Problem was man sich da schnell einhandeln kann ist eher das sich die Programme mit denen man sie geschrieben hat, weiter entwickeln und wenn man sich nicht auf Python-Grunddatentypen beschränkt, kann es sein dass die gespeicherten Daten und Namen nicht mehr zum Programm passen. Wenn man also etwas umbenennt oder in ein anderes Modul verschiebt, oder bei Klassen Attribute hinzufügt oder weglässt, passen die Daten im Pickle nicht mehr und können zu Problemen führen.

`shelve` benutzt für die Werte selbst `pickle`. Ist also keine Lösung wenn man `pickle` vermeiden möchte.

@mampfgnom: Ebenfalls eine einfache Lösung, die ohne Zusatzmodule auskommt, wäre es nicht einfach so Python-Listen mit `str()` oder ähnlichem in Zeichenketten umzuwandeln, sondern dass explizit selbst zu machen und dann für die beiden „Ebenen” verschiedene Trennzeichen zu verwenden. Also Beispielsweise: ``'1,2,3,12;13;14'``. Das lässt sich in zwei Schritten einfach und eindeutig mit `slit()`-Aufrufen trennen.

Ein Standardformat wie JSON wäre aber meiner Meinung nach immer besser, denn dafür gibt es für die verschiedensten Programmiersprachen robuste Parser und auch Generatoren.
mampfgnom
User
Beiträge: 8
Registriert: Mittwoch 6. Juni 2012, 10:10

Ich war gestern krank, weswegen ich mich erst heute melde.

Das mit dem Pythonupdate wird wohl nichts. Der Systemadministrator macht keine Anstalten was zu ändern^^

@BlackJack: Die Idee mit den Kommata und Semikola finde ich gut und werde das so auch mal umsetzen.
Hyperion hat geschrieben: Man kann aufgrund der Unerfahrenheit des OP natürlich generell mal nachfragen, ob eine Serialisierung wirklich erforderlich ist...
Ja ich glaube das ich wirklich nicht erforderlich^^

Also vielen Dank für die Hilfe und die guten Anregungen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

mampfgnom hat geschrieben: Das mit dem Pythonupdate wird wohl nichts. Der Systemadministrator macht keine Anstalten was zu ändern^^
Naja, Admins sind idR. eher nicht dafür bekannt, schnell zu agieren ;-) Meiner Erfahrung nach kann man als normaler Studi da wenig bewegen - außer man hat einen persönlichen Draht zu einem Admin. Ansonsten bringt es eher etwas, wenn ein Assistent oder gar Professor Druck macht.
mampfgnom hat geschrieben: @BlackJack: Die Idee mit den Kommata und Semikola finde ich gut und werde das so auch mal umsetzen.
Also doch Serialisierung :-D ?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten