Schrift
[thread]12352[/thread]

Zeilen einlesen und nach dritter Spalte sortieren

Leser: 5


<< |< 1 2 3 4 5 >| >> 49 Einträge, 5 Seiten
leo11
 2008-08-14 08:06
#113487 #113487
User since
2008-08-14
250 Artikel
BenutzerIn
[default_avatar]
Hallo liebe Perl Gemeinde.

Ich habe eine kleine Datei:
Zeile1;aaa;100;rrr;uuu
Zeile2;aaa;60;rrr;uuu
Zeile3;aaa;20;rrr;uuu
Zeile4;aaa;40;rrr;uuu

Sie soll hinterher wie folgt aussehen:
Zeile1;aaa;100;rrr;uuu
Zeile3;aaa;20;rrr;uuu
Zeile4;aaa;40;rrr;uuu
Zeile2;aaa;60;rrr;uuu

D.h. die erste Zeile soll unverändert die erste bleiben, alle folgenden nach der 3 Spalte aufsteigend sortiert werden. Dafür habe ich folgendes angefangen:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
use strict;
use warnings;
use IO::File;

my @zeilen=();
open (DATEI, "</tmp/testdat.txt") or die "Fehler: $!";
while(<DATEI>)
{
chomp( $_ );
print "$_ \n";
push @zeilen, [ split /;/, $_, 4 ];
}
close (DATEI);
print "$zeilen[1][2]\n"


Frage
Würdet ihr mir ein paar Tipps geben, wie ich am besten weiter vorgehe? Ich bin noch neu in Perl.

Code-Tags by betterworld[TM]
Hagen
 2008-08-14 09:49
#113488 #113488
User since
2007-09-06
233 Artikel
BenutzerIn
[default_avatar]
Schau mal auf der Seite von Christian Dühl nach, dort gibt es viele kleine Beispiele, u.a auch zum sortieren; hierfür ab Punkt 13 (sort4a.pl).
Gruß
Hagen
leo11
 2008-08-14 22:09
#113504 #113504
User since
2008-08-14
250 Artikel
BenutzerIn
[default_avatar]
Danke Dir Hagen, damit bin ich einen großen Schritt weiter.

print join(';', @{$_}), "\n" for sort vergl @zeilen;

sub vergl {
return -1 if $$a[2]<$$b[2];
return 1 if $$a[2]>$$b[2];
return 0;
}

Das macht genau das was ich benötige. Nur verstehe ich das nicht komplett. Die Funktion sort ist mir klar. Aber der Rest nicht so recht.
Daher 2 Fragen:
1.) Würde mir das jemand erklären? Speziell auch dieses $$a[2]... .

2.) Wie sorge ich dafür das die erste Zeile außen vor bleibt? Die erste Zeile soll immer die erste bleiben, unabhängig vom Wert in der Sortierspalte.
LanX-
 2008-08-14 22:21
#113505 #113505
User since
2008-07-15
1000 Artikel
BenutzerIn

user image
ojeh, ich kann dir gerade mangels Perl keinen funktionierenden Code posten aber ich würds an deiner Stelle nicht so umständlich machen.

1. Lege ein AoA @zeilen also ein Array von Arrays der Zeilen mit Ausnahme der ersten Zeile an.
2. Jeweils 2 Einträge pro Zeile, der erste ist die komplette gelesene Zeile, der zwote das Element nachdem sortiert werden soll.
3. dann sortierst du @sorted= sort { $a->[1] <=> $b->[1]} @zeilen
4. Erste Zeile ausgeben, dann den sortierten Rest von @sorted, d.h.
for my $zeile (@sorted) {print $zeile->[0]}

wie sort funktioniert zeigt dir perldoc -f sort oder ne googlesuche perldoc sort

EDIT: derefrenzierung korrigiert. @sorted eingeführt
Hagen
 2008-08-14 22:49
#113506 #113506
User since
2007-09-06
233 Artikel
BenutzerIn
[default_avatar]
zu 1

$a und $b werden benutzt um das Array zu sortieren. Hier ein einfacherers Beispiel:

Code (perl): (dl )
1
2
3
4
5
6
7
my @liste = ( 41, 37, 10, 30, 127, 512, 111 );
print "@liste\n\n";

my @sort_1 = sort @liste;                                       print "1) @sort_1  (Standard)\n";
my @sort_2 = sort { $a cmp $b } @liste;                         print "2) @sort_2  (ASCII - aufsteigend)\n";
my @sort_3 = sort { $a <=> $b } @liste;                         print "3) @sort_3  (numerisch - aufsteigend)\n";
my @sort_4 = sort { $b <=> $a } @liste;                         print "4) @sort_4  (numerisch - absteigend)\n";


über $$a[2] greifst du dann auf das Array (die Spalte zu; $a wäre das gesamte Array) zu.
Gruß
Hagen
leo11
 2008-08-14 22:49
#113507 #113507
User since
2008-08-14
250 Artikel
BenutzerIn
[default_avatar]
Hallo LanX,

wenn ich mal soweit bin, dass ich Deinen Vorschlag mal eben runterschreiben kann, bin ich stolz wie Oscar! Fürs erste wär ich erstmal froh, dass irgendwie hinzubekommen. Ich denke, dass ich mit dem angefangenen erstmal eher ein Erfolgserlebnis haben werde. Dein Vorschlag klingt gut, aber ich bin noch ncht soweit.. .
Gast Gast
 2008-08-14 23:47
#113508 #113508
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use strict;
use warnings;

my @zeilen=();
my $input_file='/tmp/testdat.txt';
open (my $fileh, '<', $input_file) or die "Fehler bei open($input_file) : $!";
while(<$fileh>)
{
   chomp($_ );
   print "$_ \n";
   push @zeilen, [ split /;/, $_, 4 ];
}
close ($fileh);

my $first_line=shift(@zeilen);
@zeilen=sort{$a->[2] <=> $b->[2]}@zeilen; # wenn es Text ist statt "<=>" "cmp" benutzen.
unsift(@zeilen, $first_line);
LanX-
 2008-08-14 23:57
#113511 #113511
User since
2008-07-15
1000 Artikel
BenutzerIn

user image
so gehts auch, dann muss die Ausgabe aber wieder mit join zusammengebastelt werden.

@leo11: erklär mal was du genau nicht verstehst, es bringt keinem was wenn man es dir auf gut Glück vorkaut.
leo11
 2008-08-15 07:38
#113522 #113522
User since
2008-08-14
250 Artikel
BenutzerIn
[default_avatar]
@Hagen:
Danke für dieses Bsp. es hat mir sehr weitergeholfen.

Dieses return -1 if $$a[2]<$$b[2]; ist mir noch unklar. Bedeutet das: Vergleiche das Element der dritten Spalte der Zeile x mit dem Element der dritten Spalte der Zeile Y und gib -1 zurück wenn es kleiner ist?

Und dann noch der Aufruf:
Code (perl): (dl )
print join(';', @{$_}), "\n" for sort vergl @zeilen;

Bedeutet das: Füge alle Felder eines Arrays semikolonsepariert zu einem String zusammen und gib die nach der Vergleichsfunktion sortierten Zeilen aus? Bedeutet dass es werden hier erst die Zeilen sortiert und dann zusammengefügt? Also von rechts nach links?

@LanX-:
Dir auch vielen Dank. Vielleicht komme ich heut Abend dazu Deinen Lösungsvorschlag mal zu probieren. Spätestens am WE werd ichs mal versuchen.

@Gast
Danke. Es hilft sehr einfach mal eine fertige Lösung zu sehen. Das
Code (perl): (dl )
print join(';', @{$_}), "\n" for @zeilen;   #sortiert wieder ausgeben

habe ich selbst hinbekommen, was mich freut.

Bedeutet die Zeile:
Code (perl): (dl )
@zeilen=sort{$a->[2] <=> $b->[2]}@zeilen

Das eine Zeile nach oben verschoben wird, wenn das Element in der dritten Spalte kleiner ist?
Gast Gast
 2008-08-15 08:50
#113523 #113523
leo11+2008-08-15 05:38:14--
@Hagen:
Danke für dieses Bsp. es hat mir sehr weitergeholfen.

Dieses return -1 if $$a[2]<$$b[2]; ist mir noch unklar. Bedeutet das: Vergleiche das Element der dritten Spalte der Zeile x mit dem Element der dritten Spalte der Zeile Y und gib -1 zurück wenn es kleiner ist?
Genau. "sort" schiebt einen Arrayeintrag nach oben wenn, die Vergleichsopperation -1 zurück liefert, lässt den Eintrag wo er ist wenn 0 gemeldet wird und schiebt bei 1 nach unten. (oder umgekehrt ... mußt du ausprobieren wie herum er sortiert :) )

leo11+2008-08-15 05:38:14--
Bedeutet die Zeile:
Code (perl): (dl )
@zeilen=sort{$a->[2] <=> $b->[2]}@zeilen

Das eine Zeile nach oben verschoben wird, wenn das Element in der dritten Spalte kleiner ist?
"<=>" liefert -1 zurück wenn a<b, 0 wenn a==b und 1 wenn a>b. (oder umgekehrt ... schwehr zu behalten das) Ähnliches gilt für "cmp" nur halt für Buchstaben.
<< |< 1 2 3 4 5 >| >> 49 Einträge, 5 Seiten



View all threads created 2008-08-14 08:06.