Textdatei umformatieren

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
at2511
User
Beiträge: 2
Registriert: Montag 13. September 2010, 21:21

Bin absoluter Python-Neuling und brauche dringend ein paar Tips die mir weiterhelfen.

Habe folgende txt-Datei (Auszug) die ich umformatieren muss:


KILOME 0.0113
X-KOO -16.07 -6.87 -2.99 0.00 1.80 4.65
5.20 5.58 6.00 6.42 6.80 7.35
Y-KOO 53.72 53.80 53.80 53.76 53.53 52.14
51.48 51.23 51.18 51.23 51.48 52.07
KILOME 0.056
X-KOO -167.00 -148.70 -16.06 0.00 1.00 4.65
5.20 5.58 6.00 6.42 6.80 7.35
9.00 10.15 28.62
Y-KOO 55.50 53.59 53.57 53.58 53.44 52.27
51.69 51.44 51.39 51.44 51.69 52.33
53.18 53.94 60.32


Ergebnis soll folgendermaßen aussehen:

KILOME X-KOO Y-KOO
0.0113 -16.07 53.72
0.0113 -6.87 53.80
...
0.056 28.62 60.32



Zeilenweises einlesen der Datei und Ausgabe in eine neue Datei habe ich noch hin bekommen, aber jetzt hakt es völlig bei dem pärchenweise zusammensetzen aus unterschiedlichen Zeilen.
Mache ich das am Besten über eine Liste? Wie greift man auf einzelne Einträge einer Listenzeile zu?
Freue mich über eine paar Tips in die richtige Richtung!
BlackJack

@at2511: Man könnte sich da einen Zustandsautomaten basteln und den als Programm umsetzen.
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

Da ich mich ein bisschen mit PLY (Python Lex-Yacc) beschäftigte, habe ich deine Aufgabe damit umgesetzt (Vielleicht ein bisschen übertrieben).
Hier meinen Vorschlag:
http://www.python-forum.de/pastebin.php?mode=view&s=65

gegen Verbesserungsvorschläge habe ich nichts einzuwenden...
BlackJack

Ich habe mich auch mal dran versucht, mit Bordmitteln: http://paste.pocoo.org/show/262097/

Das ist der zweite Anlauf. Der erste war auf der einen Seite einfacher, aber auf der anderen Seite in *einer* Funktion die viel zu lang war.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Ich bin da eher ein Freund kurzer Lösungen:

Code: Alles auswählen

infile = open("old.txt")
data = infile.read()
infile.close()
outfile = open("new.txt","w")
outfile.write("KILOME X-KOO Y-KOO\n")
for entry in data.split("KILOME")[1:]:
    vals = entry.split()
    km = vals.pop(0)
    lgs = vals.index("Y-KOO")
    for x,y in zip(vals[1:lgs],vals[lgs+1:]):
        outfile.write("%s %s %s\n" %(km,x,y))
outfile.close()
Ja, ich weiß, dass man Dateien anders einlesen sollte ....
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

Meine Lösung möchte ich auch nur kurz einstellen, weil sie seit gestern auf der HD liegt ;)

Code: Alles auswählen

import re
import StringIO

s= """KILOME 0.0113
X-KOO -16.07 -6.87 -2.99 0.00 1.80 4.65
5.20 5.58 6.00 6.42 6.80 7.35
Y-KOO 53.72 53.80 53.80 53.76 53.53 52.14
51.48 51.23 51.18 51.23 51.48 52.07
KILOME 0.056
X-KOO -167.00 -148.70 -16.06 0.00 1.00 4.65
5.20 5.58 6.00 6.42 6.80 7.35
9.00 10.15 28.62
Y-KOO 55.50 53.59 53.57 53.58 53.44 52.27
51.69 51.44 51.39 51.44 51.69 52.33
53.18 53.94 60.32"""

l = re.split(" |\n", s)
d = []
current_element = None

elements = ["X-KOO", "Y-KOO", "KILOME"]
for field in l:
    if field == "KILOME": 
        current_element = field
        d.append({"KILOME":None,"X-KOO":[], "Y-KOO":[]})
        continue
    elif field == "X-KOO" or field == "Y-KOO":
        current_element = field
        continue

    for e in elements:
        if current_element == "KILOME":
            d[-1]["KILOME"] = field
            break
        elif current_element == e and field != e:
            d[-1][e].append(field)
            break

for dataset in d:
    print "\n\nKILOME" + "\t\t" + "X-KOO" + "\t\t" + "Y-KOO"
    for i in range(0, len(dataset["X-KOO"])):
        print dataset["KILOME"] + "\t\t"+ dataset["X-KOO"][i] + "\t\t" + dataset["Y-KOO"][i]


BlackJack

Inspiriert von DaMutz auch noch eine Lösung mit einem Parser, in diesem Fall `pyparsing`:

Code: Alles auswählen

from itertools import izip, repeat
from pyparsing import Group, OneOrMore, Regex, StringEnd, Suppress, ZeroOrMore

HEADERS = KILOMETER, X_COORDINATES, Y_COORDINATES = 'KILOME', 'X-KOO', 'Y-KOO'


def define_grammar():
    number = Regex(r'-?[0-9]+(\.[0-9]*)?')
    numbers = OneOrMore(number)
    kilometer = Suppress(KILOMETER) + number
    x_coordinates = Group(Suppress(X_COORDINATES) + numbers)
    y_coordinates = Group(Suppress(Y_COORDINATES) + numbers)
    record = Group(kilometer + x_coordinates + y_coordinates)
    records = ZeroOrMore(record)
    return records


def transform(ast):
    yield HEADERS
    for kilometer, x_coordinates, y_coordinates in ast:
        for row in izip(repeat(kilometer), x_coordinates, y_coordinates):
            yield row


def main():
    grammar = define_grammar()
    ast = grammar.parseFile('test.txt')
    for row in transform(ast):
        print ' '.join(row)


if __name__ == '__main__':
    main()
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dann hoffen wir mal, dass den OP das auch immer noch interessiert ...
Benutzeravatar
DaMutz
User
Beiträge: 202
Registriert: Freitag 31. Oktober 2008, 17:25

numerix hat geschrieben:Dann hoffen wir mal, dass den OP das auch immer noch interessiert ...
Das spielt mir keine Rolle, ich habe was gelernt und das ist die Hauptsache (für mich auf jeden Fall).

@BJ: Deine pyparsing Lösung finde ich sehr schön. Im 'Programming in Python 3' Buch ist PLY und pyparsing erklärt. Im Buch hat mir PLY besser gefallen, darum habe ich es auch damit versucht, aber die pyparsing Methode ist kompakter. Das liegt eventuell auch daran, dass ich es nicht sehr geschickt implementiert habe...
at2511
User
Beiträge: 2
Registriert: Montag 13. September 2010, 21:21

:D Vielen Dank für die tolle Hilfe!!
Ich habe aus Zeitmangel nur die kurze Lösung ausprobiert und sie funktioniert genauso wie ich sie benötige.
Antworten