PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : csv Datei alphabetisch sorieren, nach drei Spalten



craano
22-02-2007, 20:24
Hallo,
ich verarbeite viele komma-separierten Dateien (.csv) mit Perl.

Nun stehe ich vor einem Problem. Ich möchte die einzelnen Zeilen alphabetisch sortieren.
Die Zeilen in der Reihenfolge einer alphabetisch sorierten Spalten auszugeben ist kein Problem, ich möchte aber, wenn die erste Spalte gleiche Inhalte aufweist die Zeilen als zweites Kriterium nach der zweiten Spalten und als drittes Kriterium nach der dritten Spalten sortieren.

Ihr könnt Euch das vorstellen wie die Sortierfunktion in Open Office für eine Tabellen anhand von mehreren Spalten (Im Menu Daten).

Wie kann ich das am besten bewerkstelligen?

1. Ich lese die Datei zeilenweise ein.
2. Ich splitte die Zeilen anhand der Trennzeichen und lege die einzelnen Elemente in Aarrays?
3. Wenn ich nun das Array der ersten Spalte alphabetisch sortiere, dann zerreißt es mir ja die ganzen Zeilen, weil die anderen Arrays nicht mit umsortiert werden!
Das Speichern in unterschiedliche Arrays scheint also nicht ideal.

Vor vielen geschachtelten Arrays schrecke ich ein wenig zurück, da man da schnell den Überblick verliert.

Habt Ihr eine Idee, wie ich mein Vorhaben am besten lösen kann?
Gibt es vielleicht ein fertiges Perl Modul, welches diese Aufgabe lösen kann?

Grüße.
craano.

Molaf
22-02-2007, 22:30
Ein Modul wäre natürlich die beste Lösung, allerdings geht eine Sortierung auch zeilenweise, wenn man die Spalten ja nach Sortierreihenfolge weiter nach vorne oder hinten bringt, un dann ein neues Array erstellt, indem man die Spalten wieder als Zeilen zusammenbringt (mithilfe der Trennzeichen).

Nach einem sort (das sort geht zeichenweise immer tiefer in die Zeilen, wenn vordere Spalten gleich sein sollten), ist das neue Array (zeilenweise) richtig sortiert, die Zellen sind noch beisammen, nur die Spalten wurden vorher umsortiert.
Da man das aber selber gemacht hat, muss man sie sich nur merken wie, und dann zurücksortieren.

craano
22-02-2007, 23:19
Fast perfekt, so klappt das, beinah!


my @sorted_columns = sort (@columns);

Weißt Du, ob man "sort (@array)" beibringen kann "richtig" nach Zahlen zu sortierten?

Also 1,2,3,4,5,6,7,8,9,10,11,12 ...
Anstatt 1,10,11,12,...,2,21,22,...,3,31,...


Grüße.
craano.

Thomas Engelke
23-02-2007, 07:16
Weißt Du, ob man "sort (@array)" beibringen kann "richtig" nach Zahlen zu sortierten?

Kann man.


sort { a <=> b } (@array);

TME

craano
23-02-2007, 08:30
Da habe ich mich etwas falsch ausgedrückt,


sort { a <=> b } (@array);

kenne ich auch. Doch leider trifft es nicht ganz meine Absicht.
Ich lese ja alle Spalten als eine Zeile ein, sortiere die Spalten und trenne sie dann an den Trennzeichen. (Die einzelnen Felder werden dann in eine HTML - Tabelle eingefügt)
"sort { a <=> b }" sortiert jetzt aber die Zeile komplett in numerischem Kontext. Es jetzt aber so, dass nur in der dritte Spalte Zahlen auftauchen und zwar als Bestandteil eines Dateinamens. "sort { a <=> b } (@array);" nummeriert jetzt im Grunde nur die kompletten Strings durch und listet sie dann ungeordnet auf.
Im Grunde muss innerhalb der alphabetischen Sortierung die Reihenfolge für Zahlen verändert werden. Ich denke aber nicht, dass das geht.

Grüße.
craano.

Thomas Engelke
27-02-2007, 08:16
Ich denke aber nicht, dass das geht.

Eine heiße Annahme, trotzdem dir eigentlich die gesamte Sprache Perl innerhalb der geschweiften Klammern der sort-Funktion zur Verfügung steht. Gibt es dort etwas, was man mit Perl nicht erreichen kann?

So ganz klar ist mir dein Problem immer noch nicht, aber soweit ich glaube, es verstanden zu haben, hast du folgendes Problem:

Innerhalb der sort-Funktion sind die Variablen a und b nicht einzelne Werte, sondern Strings des Formates "zahl1 zahl2 buchstabenkombination". Du willst jetzt nicht alles direkt nach der Konvertierung von Zahl1 in eine Zahl numerisch sortieren, sondern bei z.B. bei Gleichheit von Zahl1 aus a und b noch Zahl2 und ggf. die Buchstabenkombination heranziehen. um zu entscheiden, welches Element "größer" ist. Dabei soll es sich teilweise um Stringvergleiche und teilweise um numerische Vergleiche handeln.

So ich das richtig verstanden habe, muß du das nur innerhalb der geschweiften Klammern ausdrücken. Dann hättest du das gewünschte Ergebnis.

TME

reneeb
27-02-2007, 12:38
Mit DBD::CSV kann man auf CSV-Dateien wie auf normale Datenbanken zugreifen. Damit dürfte auch eine Sortierung relativ einfach sein...

craano
27-02-2007, 15:26
...
Innerhalb der sort-Funktion sind die Variablen a und b nicht einzelne Werte, sondern Strings des Formates "zahl1 zahl2 buchstabenkombination". Du willst jetzt nicht alles direkt nach der Konvertierung von Zahl1 in eine Zahl numerisch sortieren, sondern bei z.B. bei Gleichheit von Zahl1 aus a und b noch Zahl2 und ggf. die Buchstabenkombination heranziehen. um zu entscheiden, welches Element "größer" ist. Dabei soll es sich teilweise um Stringvergleiche und teilweise um numerische Vergleiche handeln.

...
TME

Fast, die Zeilen der Datei sehen ungefähr so aus:

Buchstaben ; Buchstaben ; Zahlen ; Buchstaben; Zahlen
sort (@array);sortiert die Zeilen fast richtig. Lediglich bei gleichem ersten und zweiten Feld wird Feld 3 zur Sortierung heran gezogen.
Hier wird nun aber 1 < 10 < 11 < 12 < .. 19 < 2 < 20 < 21 ... < 3 ... sortiert.

Ich frage mich nun wie man sort beibringen kann nur in Feld 3 numerisch zu sortieren, ansonsten aber die Sortierreihenfolge nicht zu ändern.

@reneeb
DBD::CSV
Die Dateien wie eine Datenbank anzusprechen klingt interessant, das könnte viele Probleme vereinfachen.

Grüße.
craano.

Thomas Engelke
12-03-2007, 10:25
So ich das richtig verstanden habe, muß du das nur innerhalb der geschweiften Klammern ausdrücken. Dann hättest du das gewünschte Ergebnis.

Siehe perldoc sort, das BLOCK-Argument.

TME