2017-08-23 5 views
1

2-teilige Frage. Wie man Text analysiert und als Klassenobjekt/Attribute speichert und wie man Text aus den Klassen in einem bestimmten Format umschreiben kann.Analysieren einer Textdatei zum Speichern in Klassenobjekte und Attribute

Ich möchte durch eine Textdatei analysieren und Textabschnitte extrahieren und ein Klassenobjekt und Attribute erstellen. Es wird mehrere Klassen (Polygone, Raum, Zone, System, Zeitplan) geben. In der Originaldatei sind jedes "Objekt" und seine "Attribute" durch ".." getrennt. Ein Beispiel von einem ist unten.

"Office PSZ" = SYSTEM 
    TYPE    = PSZ 
    HEAT-SOURCE  = FURNACE 
    FAN-SCHEDULE  = "HVAC Yr Schedule" 
    COOLING-EIR  = 0.233207 
    .. 

Ich möchte diesen Text lesen und in Klassenobjekte speichern. Also "Office PSZ" wäre von der HVAC-System- oder SYSTEM-Klasse, habe nicht entschieden. 'SYSTEM' wäre eine Klassenvariable. Für diese Instanz ("Office PSZ") wäre self.TYPE PSZ. self.HEAT-SOURCE würde FURNACE, etc. entsprechen.

Ich möchte diese Objekte basierend auf ihren Attributen manipulieren. Das Endergebnis wäre jedoch, alle Daten, die manipuliert wurden, in eine Textdatei mit dem ursprünglichen Format zu schreiben. Das Endergebnis für diese Instanz kann sein.

"Office PSZ" = SYSTEM 
    TYPE    = PSZ 
    HEAT-SOURCE  = ELECTRIC 
    FAN-SCHEDULE  = "Other Schedule" 
    COOLING-EIR  = 0.200 
    .. 

Gibt es eine Möglichkeit, das Attribut name/title (idk, wie es zu nennen) zu drucken? Weil der Attributname (d. H. TYPE, HEAT-SOURCE) von der Originaldatei stammt und es einfacher wäre, nicht alle mit jeder Klasse assoziierten Attribute manuell antizipieren zu müssen.

Ich nehme an, ich könnte ein Array aller Werte auf der linken Seite von "=" und ein anderes Array für die Werte auf der rechten Seite erstellen und diese durchlaufen, während ich eine neue Textdatei schreibe/formatiere. Aber ich bin mir nicht sicher, ob das ein guter Weg ist.

Ich bin immer noch ziemlich Amateur, also könnte ich übergreifen, aber irgendwelche Vorschläge, wie ich vorgehen sollte?

+0

Es klingt wie Sie ein Objekt als * Container * verwenden möchten, dh als einen organisierten Ort, um eine Sammlung von Daten zu speichern. Sie scheinen einen Container zu haben, mit dem Sie benannte Datenelemente sammeln können. Wenn dies zutrifft, könnte es einfacher sein, ein Wörterbuch zu verwenden. Man könnte sagen: 'Office_PSZ = {'TYPE': 'PSZ', 'HEAT-SOURCE': 'ELECTRIC', ...}' Wenn Sie das Dokument 'dict' lesen, werden Sie feststellen, dass Sie beliebige Elemente hinzufügen können ein Wörterbuch, greifen Sie individuell auf sie zu, und so weiter. –

Antwort

1

Pyparsing macht es einfach, benutzerdefinierte Parser für Daten wie diese zu schreiben, und gibt geparste Daten in einem Pyparsing-Datenstrukturaufruf ParseResults zurück. ParseResults gibt Ihnen Zugriff auf Ihre geparsten Werte nach Position (wie eine Liste), nach Schlüssel (wie ein Dict) oder nach Namen, die als Python-Bezeichner nach Attribut (wie ein Objekt) funktionieren.

Ich habe meine Parsing Ihrer Daten vereinfacht, so einfach nehmen Sie alle key = value Zeile und erstellen Sie eine Struktur mit den Schlüsselzeichenfolgen als Schlüssel. Die '..' Zeilen funktionieren großartig als Terminatoren für jedes Objekt.

Ein einfacher BNF hierfür könnte wie folgt aussehen:

object ::= attribute+ end 
attribute ::= key '=' value 
key ::= word composed of letters 'A'..'Z' and '-', starting with 'A'..'Z', 
      or a quoted string 
value ::= value_string | value_number | value_word 
value_word ::= a string of non-whitespace characters 
value_string ::= a string of any characters in '"' quotes 
value_number ::= an integer or float numeric value 
end ::= '..' 

einen pyparsing Parser zu implementieren, arbeiten wir unten pyparsing Unterausdrücke zu definieren. Dann verwenden wir Python '+' und '|' Operatoren niedrigerer Ebene Ausdrücke höherer Ebene diejenigen zu montieren:

import pyparsing as pp 

END = pp.Suppress("..") 
EQ = pp.Suppress('=') 

pyparsing einige vordefinierte Ausdrücke für Zeichenfolgen in Anführungszeichen und Numerik enthält; Die Zahlen werden automatisch in Ints oder Floats umgewandelt.

value_number = pp.pyparsing_common.number 
value_string = pp.quotedString 
value_word = pp.Word(pp.printables) 
value = value_string | value_number | value_word 

Für unseren Attributschlüssel werden wir das Zwei-Argument-Formular für Word verwenden.Das erste Argument ist eine Zeichenfolge mit zulässigen führenden Zeichen, und das zweite Argument ist eine Zeichenfolge der zulässigen Körperzeichen. Wenn wir nur `Wort (alphas + '-') geschrieben haben, dann würde unser Parser" --- "als legalen Schlüssel akzeptieren.

key = pp.Word(pp.alphas, pp.alphas + '-') | pp.quotedString 

Ein Attribut Definition ist nur ein Schlüssel, ein Zeichen ‚=‘, und ein Wert

attribute = key + EQ + value 

Schließlich werden wir einige der komplexeren Funktionen von pyparsing verwenden. Die einfachste Form wäre nur "pp.OneOrMore (Attribut) + END", aber dies würde uns nur einen Stapel von geparsten Tokens ohne Struktur zurückgeben. Die Group-Klasse strukturiert die eingeschlossenen Ausdrücke so, dass ihre Ergebnisse als Unterliste zurückgegeben werden. Wir werden jedes Attribut als seine eigene Unterliste mit Group abfangen. Dict wendet eine Benennung auf die Ergebnisse an, wobei der Text von jedem Schlüsselausdruck als Schlüssel für diese Gruppe verwendet wird. Schließlich wird die ganze Sammlung von Attributen wieder Group'ed werden, diesmal repräsentiert alle Attribute für ein einzelnes Objekt:

object_defn = pp.Group(pp.Dict(pp.OneOrMore(pp.Group(attribute)))) + END 

diesen Ausdruck zu verwenden, werden wir unser Parser definieren als:

parser = pp.OneOrMore(object_defn) 

und analysieren, um die Probe Zeichenfolge mit:

objs = parser.parseString(sample) 

die objs Variable, die wir zurückbekommen wird ein pypar sing ParseResults, das wie eine Liste der gruppierten Objektattribute funktioniert. Wir können sehen nur die analysierten Attribute als Liste von Listen asList mit():

for obj in objs: 
    print(obj.asList()) 

[['"Office PSZ"', 'SYSTEM'], ['TYPE', 'PSZ'], ['HEAT-SOURCE', 'FURNACE'], 
['FAN-SCHEDULE', '"HVAC Yr Schedule"'], ['COOLING-EIR', 0.233207]] 

Wenn wir nicht die Dict Klasse benutzt hatte, würde dies alles haben wir bekommen würde, aber da wir tat Einsatz dict, können wir die Attribute als Python dict siehe auch:

for obj in objs: 
    print(obj.asDict()) 

{'COOLING-EIR': 0.233207, '"Office PSZ"': 'SYSTEM', 'TYPE': 'PSZ', 
'FAN-SCHEDULE': '"HVAC Yr Schedule"', 'HEAT-SOURCE': 'FURNACE'} 

wir können auch nach Name Zugriff benannte Felder, wenn sie als Python-IDs arbeiten. In Ihrem Beispiel ist "TYPE" die einzige legale ID, so dass Sie sehen können, wie Sie es hier ausdrucken können. Dort ist auch eine dump() Methode, die die Ergebnisse in Listenform gibt, gefolgt von einer eingerückten Liste von definierten Schlüsselpaaren. (Ich habe auch gezeigt, wie Sie die Liste verwenden können und DIKT Typ Zugriff direkt auf die ParseResults Objekt, ohne zu konvertieren oder dict-Typen zur Liste):

for obj in objs: 
    print(obj[0]) 
    print(obj['FAN-SCHEDULE']) 
    print(obj.TYPE) 
    print(obj.dump()) 

['"Office PSZ"', 'SYSTEM'] 
"HVAC Yr Schedule" 
PSZ 
[['"Office PSZ"', 'SYSTEM'], ['TYPE', 'PSZ'], ['HEAT-SOURCE', 'FURNACE'], 
['FAN-SCHEDULE', '"HVAC Yr Schedule"'], ['COOLING-EIR', 0.233207]] 
- "Office PSZ": 'SYSTEM' 
- COOLING-EIR: 0.233207 
- FAN-SCHEDULE: '"HVAC Yr Schedule"' 
- HEAT-SOURCE: 'FURNACE' 
- TYPE: 'PSZ' 

Hier ist der vollständige Parser-Code für Sie arbeiten von:

import pyparsing as pp 

END = pp.Suppress("..") 
EQ = pp.Suppress('=') 

value_number = pp.pyparsing_common.number 
value_string = pp.quotedString 
value_word = pp.Word(pp.printables) 
value = value_string | value_number | value_word 

key = pp.Word(pp.alphas, pp.alphas+"-") | pp.quotedString 

attribute = key + EQ + value 
object_defn = pp.Group(pp.Dict(pp.OneOrMore(pp.Group(attribute)))) + END 

parser = pp.OneOrMore(object_defn) 
objs = parser.parseString(sample) 

for obj in objs: 
    print(obj.asList()) 

for obj in objs: 
    print(obj.asDict()) 

for obj in objs: 
    print(obj[0]) 
    print(obj['FAN-SCHEDULE']) 
    print(obj.TYPE) 
    print(obj.dump()) 
Verwandte Themen