Seite 1 von 1
Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 11:36
von USER67
Guten Tag,
Code: Alles auswählen
Sonnenschein = "Die Sonne scheint: [1, "Maier: begeistert"], Die Wolken sind grau: [2,"Udu: traurig"]"
Ich würde gerne nach ":" spliten, allerdings soll es nur oberflächlich passieren, in den Listen soll es nicht geschehen.
Wie könnte man das hinkriegen?
Mfg
Udu
Re: Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 11:41
von Hyperion
Könntest Du nicht für das Beispiel mal das von Dir gewünschte Endresultat angeben? Nur als Sicherheit, dass man Dich auch wirklich verstanden hat.
Prinzipiell müßtest Du da wohl mit einem Zustandsautomaten arbeiten (außerhalb einer Liste, oder innerhalb).
Re: Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 11:47
von USER67
Hallo,
ja natürlich. Also ich möchte einen vorhandenen Text analysieren.
Dabei sollen solche Fragmente in einem Dictionary abgelegt werden, wobei die oberflächlichen Statements wie "Die Sonne scheint:" als "Keys" gesetzt werden.
In der Form
Code: Alles auswählen
Dictionary = {
"Die Sonne scheint": [1, "Maier: begeistert"],
"Die Wolken sind grau": [2,"Udu: traurig]"
...
}
Re: Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 12:01
von BlackJack
@USER67: So etwas ist oft komplizierter als es auf den ersten Blick scheint. Wenn man Einfluss auf das erzeugende Programm hat, sollte man so etwas gar nicht erst erzeugen, sondern lieber ein standardisiertes Format verwenden, für das es bereits fertige Parser gibt. XML oder JSON zum Beispiel.
Sonst muss man sich selber einen Parser basteln, zum Beispiel mit Hilfe einer entsprechenden Bibliothek. Hier mal ein Beispiel mit `pyparsing`:
Code: Alles auswählen
from pprint import pprint
import pyparsing as pp
def main():
sonnenschein = ('Die Sonne scheint: [1, "Maier: begeistert"],'
' Die Wolken sind grau: [2,"Udu: traurig"]')
key = pp.CharsNotIn(':')
value = pp.Combine('[' + pp.CharsNotIn(']') + ']')
item = pp.Group(key + pp.Suppress(':') + value)
items = pp.Dict(pp.delimitedList(item))
result = items.parseString(sonnenschein)
pprint(result.asDict())
if __name__ == '__main__':
main()
Ausgabe:
Code: Alles auswählen
$ python forum5.py
{'Die Sonne scheint': '[1, "Maier: begeistert"]',
'Die Wolken sind grau': '[2,"Udu: traurig"]'}
Wie man sieht sind die "Listen" noch Zeichenketten. Da müsste man die Grammatik noch ein wenig erweitern.
Re: Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 12:07
von /me
USER67 hat geschrieben:
Code: Alles auswählen
Sonnenschein = "Die Sonne scheint: [1, "Maier: begeistert"], Die Wolken sind grau: [2,"Udu: traurig"]"
Ich würde gerne nach ":" spliten, allerdings soll es nur oberflächlich passieren, in den Listen soll es nicht geschehen.
Erst einmal müsste der Code wie folgt aussehen:
Code: Alles auswählen
Sonnenschein = 'Die Sonne scheint: [1, "Maier: begeistert"], Die Wolken sind grau: [2,"Udu: traurig"]'
Das genannte Beispiel führt zu einem Syntaxfehler.
Jetzt sollte man auch noch klar stellen, dass es dort nirgendwo eine Liste gibt. Es gibt einen String der eckige Klammern enthält, aber das ist auch schon alles. Ich möchte hier von vorneherein sicher gehen, dass hier nicht von falschen Voraussetzungen ausgegangen wird.
Re: Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 12:11
von Hyperion
Also willst Du eigentlich nach den Kommata trennen, die einen Block (Text + ":" + "[]"-Ausdruck) vom anderen trennt. Erst danach willst Du ein solches Token dann am ersten ":" trennen. So interpretiere ich dein Beispiel.
Ich hätte dieses Vorgehen vorgeschlagen:
Code: Alles auswählen
In [27]: data = u"""Die Sonne scheint: [1, "Maier: begeistert"], Die Wolken sind grau: [2,"Udu: traurig"]"""
In [30]: for token in re.findall("[ \w]*: \[.*?\]", data):
....: print token
....:
....:
Die Sonne scheint: [1, "Maier: begeistert"]
Die Wolken sind grau: [2,"Udu: traurig"]
Damit hättest Du die Tokens. Wenn Du den RegExp erweiterst, kannst Du auch gleich die beiden Teile rausfiltern:
Code: Alles auswählen
In [34]: re.findall("(?P<key>[ \w]*): (?P<value>\[.*?\])", data)
Out[34]:
[(u'Die Sonne scheint', u'[1, "Maier: begeistert"]'),
(u' Die Wolken sind grau', u'[2,"Udu: traurig"]')]
Das kannst Du direkt in ein Dictionary wandeln.
Re: Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 12:53
von BlackJack
Ich würde da noch ein r'\s*' am Anfang schreiben, damit beim zweiten Shlüssel das führende Leerzeichen verschwindet.
Code: Alles auswählen
In [712]: dict(re.findall(r'\s*(?P<key>[^:]+): (?P<value>\[.*?\]),?', data))
Out[712]:
{'Die Sonne scheint': '[1, "Maier: begeistert"]',
'Die Wolken sind grau': '[2,"Udu: traurig"]'}
Re: Innerhaln eines bestimmten Bereichs splitten
Verfasst: Donnerstag 23. September 2010, 15:44
von Hyperion
@BlackJack: Gute Idee!
Wobei mir Deine Lösung eh besser gefällt; sie ist leichter erweiterbar und vor allem auch flexibler hinsichtlich innerer Konstrukte. Wir wissen ja nicht, inwiefern die Syntax innerhalb der "[]"-Paare immer gleich bleibt.