Seite 1 von 1

Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 14:09
von dax5
Hallo,

ich habe leider keine passende Lösung für mein spezielles Problem gefunden und würde mich freuen, hier mein Glück zu finden :)
Konkret habe ich folg. Problem:

Alle Dateien eines Ordners enthalten XML-Dateien, die alle eingelesen/geparsed werden sollen, was prinzipiell schon funktioniert. Je nach Dateiname, welcher die "Kategorie" der Obj. beschreibt, sollen die gelesenen XML-Objekte gruppiert, also am Einfachsten in eine Liste "kategorieX" gespeichert werden.
Die Dateien sehen z.B. wie folgt aus:
fahrzeugX1_markeY1_baujahrZ1.xml
fahrzeugX1_markeY1_baujahrZ2.xml => Die 3 XML-Objekte dieses 3er Blocks (Kategorie: selbes Fahrzeug und selbe Marke) sollen in eine Liste, da sie zur selben KategorieXY gehören
fahrzeugX1_markeY1_baujahrZ3.xml
...
fahrzeugX1_markeY2_baujahrZ4.xml
fahrzeugX1_markeY2_baujahrZ5.xml
fahrzeugX1_markeY2_baujahrZ6.xml
...
fahrzeugX2_markeY3_baujahrZ7.xml

Dafür habe ich erst mal eine Liste erstellt, die alle Dateinamen aufnimmt:

Code: Alles auswählen

filesAll = [ f for f in listdir(pfad) if isfile(join(pfad,f)) ] 
Abhängig vom Dateinamen wird dann die entsprechende Datei geparsed und in eine Liste/Gruppe gespeichert:

Code: Alles auswählen

for f in filesAll:
    if 'fahrzeugX1_markeY1' in f:
        xmlObjList_fahrzeugX1_markeY1.append( parse(pfad + f) )    # = Liste von parsed XML-Objekten derselben Kategorie fahrzeugX1_markeY1
    elif 'fahrzeugX1_markeY2' in f:
        xmlObjList_fahrzeugX1_markeY2.append( parse(pfad + f) ) 
    usw.
Da ich etliche Kategorien vorzunehmen habe, wäre diese Lösung zwar lauffähig aber extrem aufwändig und unflexibel.
Das eigentliche Problem ist aber, dass in den if-Verzweigungen noch Funktionsaufrufe implementiert werden müssen, wo als akt. Parameter "xmlObjList_KategorieX", also eine Liste mit gruppierten XML-Objekten übergeben werden müssen, also in jeder Verzweigung folgender Aufruf:

Code: Alles auswählen

       funktion(xmlObjList_KategorieXY)
Mir wäre schon sehr geholfen, wenn ich die Liste "filesAll" mit allen Dateinamen/Strings umwandeln könnte in eine Liste mit XML-Objekten, die diesen Dateinamen entsprechen, also [xmlObjList_Kategorie1, xmlObjList_Kategorie2, ...], damit ich diese Liste der Funktion "funktion()" als Parameter übergeben kann.

Hoffe, die Beschreibung war nicht zu kompliziert und würde mich über Ideen freuen. Danke schon mal!

Re: Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 14:24
von cofi
Hier eine Loesung, die dir deine Dateinamen gruppiert - sofern die Namen tatsaechlich konsistent so einem Muster entsprechen.

Code: Alles auswählen

import re
from collections import defaultdict

def group_filenames(filenames, pattern):
    grouping = defaultdict(list)
    for filename in filenames:
        match = re.match(pattern, filename)
        if match:
            grouping[match.group(1) + match.group(2)].append(filename)
    return grouping.values()

filenames = ['fahrzeugX1_markeY1_baujahrZ1.xml', 'fahrzeugX1_markeY1_baujahrZ2.xml', 'fahrzeugX1_markeY1_baujahrZ3.xml', 'fahrzeugX2_markeY1_baujahrZ1.xml']
pattern =  r'fahrzeug(.*?)_marke(.*?)_.*'

>>> group_filenames(filenames, pattern) 
[['fahrzeugX2_markeY1_baujahrZ1.xml'],
 ['fahrzeugX1_markeY1_baujahrZ1.xml',
  'fahrzeugX1_markeY1_baujahrZ2.xml',
  'fahrzeugX1_markeY1_baujahrZ3.xml']]
Ich hoffe ich habe dich da jetzt richtig verstanden.

Re: Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 15:02
von dax5
Hey danke erst mal fürs Lesen meines Romans und deiner Hilfe!
Knackpunkt bei deiner Lösung ist, das Pattern einer Kategorie aus dem Dateinamen zu ziehen. Im Grunde also wieder mein Dilemma, dass ich nicht in der Lage bin, Strings/Dateinamen in einen Variablenbezeichner umzuwandeln. Da es (vorerst) mind. 25 Kategorien gibt, müsste ich dann wieder 25 Patterns erstellen.

Re: Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 15:11
von /me
dax5 hat geschrieben:Im Grunde also wieder mein Dilemma, dass ich nicht in der Lage bin, Strings/Dateinamen in einen Variablenbezeichner umzuwandeln. Da es (vorerst) mind. 25 Kategorien gibt, müsste ich dann wieder 25 Patterns erstellen.
Hier ist ohnehin wohl eher eine Liste oder ein Dictionary als Datenstruktur geeignet statt lauter einzelne Variablen.

Re: Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 15:25
von Sirius3
@dax5: Sinn eines Pattern ist es ja gerade dass es ein Muster gibt, das die Gruppierung eindeutig macht. Bei Dir am Beispiel eben das Paar (fahrzeug??, marke??).
Diese Paar dient Dir dann als Schlüssel für ein Dictionary (z.B. xmlObjListe[fahrzeug, marke]). Wenn Du in Deiner Lösung anfängst, variable Variablennamen zu benutzen,
machst Du schon etwas falsch.

Re: Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 15:27
von mcdwerner
So verstehe ich das Problem:

Code: Alles auswählen

def my_pattern(filename):
    return "important part of filename"

files_all = [ f for f in listdir(pfad) if isfile(join(pfad,f)) ]

groups = dict()

for filename in files_all:
    group = my_pattern(filename)
    if groups.get(group) is None:
        groups[group] = list()
    groups[group].append(filename)
jetzt musst Du nur noch überlegen, wie my_pattern() mit dem Filenamen umgehen soll (z.B. alles was vor dem 2. Underscore steht?)
Dann hast Du alle zusammengehörigen Filenamen in einer Liste im Dictionary groups.
Damit kannst Du dann gebündelt weiterarbeiten.

edit: typo

Re: Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 17:35
von dax5
Ok, vielen Dank allen! Denke, das Dict + Pattern ist die beste Idee und ich versuch es mal auf mein Projekt zu übertragen. Weitere Nachfragen halte ich mir mal offen :)

Re: Objekte (aus Dateien geparsed) gruppieren in eine Liste

Verfasst: Donnerstag 14. Februar 2013, 17:46
von cofi
Wenn du das `.values()` aus der `return` Anweisung in meiner Funktion streichst, hast du es schon ;) Vorausgesetzt es gibt tatsaechlich ein Namensmuster bei den Dateinamen, wenn nicht wirst du wohl auf eine eigene Extraktionsfunktion zurueckgreifen muessen, wie mcdwerner es angedeutet hat.