jonny: Spalten sortieren

Hallo,

mein Vorhaben ist recht simple zu erklären. Ich habe eine Datei mit etlichen Daten in Tabellenform. Beispiel:

Datei mit 6 Spalten

20041215 2.3 812.2 48 32 20
20041215 31.9 12.2 34 12 54
20041215 1.5 512.2 96 2 2
20041215 1231.3 2.2 8 32 60
...

Nun möchte ich gerne die Daten nach einer bestimmten Spalte sortieren und das möglichst Dynamisch. Das heißt dem Script wird als Argument die Spaltennummer mitgegeben, nach der das Script sortieren soll.

Mein erster Ansatz war, jede Spalte in ein eigenes Array zu laden mit einem Index am Ende jedes Strings, um es dann im Nachhein nach dem Index im String alles sortiert auflösen zu können. Das würde auch klappen, aber bestimmt gibt es bessere Lösungen.

Hat einer von euch Proggis ein nettes Beispiel im Fundus reicher Skriptsammlungen und kann es mir eins Posten? :-)

Ich wäre super dankbar für Tipps.

Mfg,
Jonny

  1. Nur damit ich dein Problem verstehe:

    Du möchtest, wenn man die Tabelle zum Beispiel im IE sieht, dass man in der ersten Zeile auf irgendeine Spalte klickt und er danach sortiert? (aufwärts sowie abwärts)

    also DB-unabhängig?

    1. Hallo,

      Du möchtest, wenn man die Tabelle zum Beispiel im IE sieht, dass man in der ersten Zeile auf irgendeine Spalte klickt und er danach sortiert? (aufwärts sowie abwärts)

      ja :-)

      Mfg,
      Jonny

  2. mein Vorhaben ist recht simple zu erklären. Ich habe eine Datei mit etlichen Daten in Tabellenform. Beispiel:

    und genauso simpel ist die Lösung: Nimm eine Datenbank, diese sind für genau solche Situationen konstruiert.

    Ich habe auch lange an solchen Fragestellungen mit selbstgebauten Code rumgebastelt. Sobald du das erste mal ein bisschen mit SQL gemacht hast, willst du sowas nie wieder von Hand machen.

    Aber na gut:

    Datei mit 6 Spalten

    20041215 2.3 812.2 48 32 20
    20041215 31.9 12.2 34 12 54
    20041215 1.5 512.2 96 2 2
    20041215 1231.3 2.2 8 32 60

    ...

    Nun möchte ich gerne die Daten nach einer bestimmten Spalte sortieren und das möglichst Dynamisch. Das heißt dem Script wird als Argument die Spaltennummer mitgegeben, nach der das Script sortieren soll.

    #! /usr/bin/perl -w
    use strict;

    my @daten;
    my $test;
    foreach(<DATA>)
    {
        chomp;
        push @daten, [split/ /, $_];
    }
    $test = [ sortiereNachSpalte(0) ];
    output( $test, 0 );

    $test = [ sortiereNachSpalte(1) ];
    output( $test, 1 );

    $test = [ sortiereNachSpalte(2) ];
    output( $test, 1 );

    sub sortiereNachSpalte
    {
        my $x = shift || 0;
        return sort { $a->[$x] <=> $b->[$x]} @daten;
    }

    sub output
    {
        my $arr = shift;
        my $spalte = shift || 0;
        my $nr = 1;
        print "sortiert nach Spalte: $spalte\n";
        foreach( @$arr)
        {
            print sprintf "Line %02d:%8s %7.2f %5.1f %02d %2d %2d\n", $nr, @$_;
            $nr++;
        }
    }

    __DATA__
    20041215 2.3 812.2 48 32 20
    20041215 31.9 12.2 34 12 54
    20041215 1.5 512.2 96 2 2
    20041215 1231.3 2.2 8 32 60

    Das geht aber nur, wenn die Daten auch Zahlen sind.

    Ansonsten muss die sortierfunktion für die Spalte so geändert werden:
    return sort { $a->[$x] cmp $b->[$x]} @daten;

    Struppi.

    1. Hallo Struppi,

      weiter unten im Forum hatte ich einen Thread bezüglich MySQL aufgemacht. Leider ist das tragbare Volumen einer MySQL Datenbank nicht gegeben. Als Oracle-DBA würde ich gerne Oracle einsetzen, aber leider wären mir die Kosten zu hoch und andere Datenbanken - ausser MySQL - haben nicht die Power, die ich mit "selbstgebastelten Code" erreichen kann.

      Aber danke _vielmals_ für das Beispiel !!!!!
      Genial!

      Mfg,
      Jonny

      1. weiter unten im Forum hatte ich einen Thread bezüglich MySQL aufgemacht. Leider ist das tragbare Volumen einer MySQL Datenbank nicht gegeben. Als Oracle-DBA würde ich gerne Oracle einsetzen, aber leider wären mir die Kosten zu hoch und andere Datenbanken - ausser MySQL - haben nicht die Power, die ich mit "selbstgebastelten Code" erreichen kann.

        Oh, hab ich grad gelesen.
        ob du aber mit meinem Beispiel 4,5 GB Daten sortieren kannst wage ich zu bezweifeln.

        Struppi.

        1. Hallo,

          ob du aber mit meinem Beispiel 4,5 GB Daten sortieren kannst wage ich zu bezweifeln.

          das werden ich schon herausfinden. Es werden keine 4-5 Gigabyte sein, aber ich werde sicherlich bis zu 1 Gigabyte Daten sortieren müssen, auch wenn die Laufzeit nicht so toll ist, aber da es kein öffentliches Projekt ist, sonder ein internes (intranet), ist das wohl ok.

          Weger der Tabellengröße... die Tabellen sind zwar riesen groß, aber ich brauche nie mehr als ca. 1,4 Mio. - nach meiner Rechnung - daraus zu selektieren, aber andersrum kann ich die Daten auch nicht trennen. Deshalb bleibe ich lieber bei Dateien, da ist eine Trennung schon besser.

          Mfg,
          Jonny

  3. Tag jonny.

    mein Vorhaben ist recht simple zu erklären. Ich habe eine Datei mit etlichen Daten in Tabellenform. [...] Nun möchte ich gerne die Daten nach einer bestimmten Spalte sortieren und das möglichst Dynamisch. Das heißt dem Script wird als Argument die Spaltennummer mitgegeben, nach der das Script sortieren soll.

    Hm, das klingt nach der Schwartzschen Transformation. Das könnte vereinfacht so aussehen:

    @sortiert = map  { $_->[0] }
                sort { $a->[1] <=> $b->[1] }
                map  { [ $_, (split / /)[$nr] ] } @zeilen;

    Zur Erklärung (von unten nach oben):

    Das letzte map erstellt aus deiner Gesamtliste @zeilen eine temporäre Liste aus anonymen (»namenlosen«) Arrays. In diesen anonymen Arrays werden das Originalelement ($_) sowie das gewünschte Feld abgelegt. Wesentlich ist hier zu wissen, dass »split / /« ein Array liefert, von dem du aber nur das Element »$nr« benötigst, nämlich die Spaltennummer, nach der sortiert werden soll (bedenke, dass das erste Element eines Arrays immer $arr[0], nicht $arr[1] ist, das musst du bei der Nummerierung der Spalten beachten).

    Diese temporäre Liste wird mittels sort sortiert. Denke daran, durch die letzte map-Anweisung hat $a->[0] den Inhalt »$_«, in $a->[1] steht das Ergebnis der split-Operation, den Vergleichsoperator musst du natürlich typenabhängig wählen.

    In der obersten map-Anweisung wird alles wieder sortiert zusammengefügt, hier mittels $_->[0] (das war die ganze Zeile, siehe meine Erklärung zum letzten map). Das Ergebnis ist eine Liste, sortiert nach Spaltennummer $nr.

    Hm, hoffentlich habe ich nicht wieder was vergessen :-)

    Siechfred

    --
    »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«
    1. Hallo,,

      @sortiert = map  { $_->[0] }
                  sort { $a->[1] <=> $b->[1] }
                  map  { [ $_, (split / /)[$nr] ] } @zeilen;

      Zur Erklärung (von unten nach oben):

      wauh ... das ist harter Tobak! Da werde ich wohl hart durchkämpfen müssen!

      Ich möchte dir gerne mal zeigen, was ich mir vorgestellt hatte und fände es klasse, wenn du es mal bewerten könntest... oder einer der anderen Proggis hier.

      Folgendes Beispiel:

      es soll nach Spalte 2 sortiert werden

      my $c=2;
      my @data0;
      my @data1;
      my @data2;
      my @data3;
      my @data4;
      my @data5;
      my $s=0;

      while(<FILE>) {
         my @tmp=split / /,$_;
         $tmp[$t]="$tmp[$t]n$t";  #n$t als Index
         $data0[$s]=$tmp[0];
         $data1[$s]=$tmp[1];
         $data2[$s]=$tmp[2];
         $data3[$s]=$tmp[3];
         $data4[$s]=$tmp[4];
         $data5[$s]=$tmp[5];
         $s++;
      }

      @data2=sort{ lc($a) cmp lc($b) } @data2;

      for(my $i=0 ; $i <= $s ; $i++) {
         my $index=$data2[$i];
         $index=~s/.*n//g;
         $data2[$i]=~s/n.*//;
         print "$data0[$index] $data1[$index] $data2[$i] $data3[$index] $data4[$index] $data5[$index]\n";
      }

      Ist das sehr schlecht?

      Schreibfehler bitte ich zu verzeihen, aber mein Grundkonstrukt sollte klar sein... hoffentlich!

      Mfg,
      Jonny

      1. Tag jonny.

        wauh ... das ist harter Tobak! Da werde ich wohl hart durchkämpfen müssen!

        Och, so schlimm ist es nun auch wieder nicht, ich habe auch nur ca. 2 Lichtjahre gebraucht, bis ich es kapiert hatte ;-)

        Ich möchte dir gerne mal zeigen, was ich mir vorgestellt hatte und fände es klasse, wenn du es mal bewerten könntest.

        Letztendlich machst du auch nichts anderes als der von mir gepostete Vorschlag, nur nicht mit einer temporären Liste, sondern mit mehreren Arrays.

        Folgendes Beispiel:
        es soll nach Spalte 2 sortiert werden
        my $c=2;
        [...]
        my $s=0;
        [...]
        while(<FILE>) {
           my @tmp=split / /,$_;
           $tmp[$t]="$tmp[$t]n$t";  #n$t als Index

        Das soll doch hier sicher $tmp[$c] = "$tmp[$c]n$s"; heißen, oder? Der Rest sieht so okay aus, wenngleich es mir sehr umständlich erscheint :-)

        Siechfred

        --
        »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«
        1. Hi,

          Das soll doch hier sicher $tmp[$c] = "$tmp[$c]n$s"; heißen, oder? Der Rest sieht so okay aus, wenngleich es mir sehr umständlich erscheint :-)

          da ich ein absoluter Perl-Noob bin, weiß ich leider nie, wann es umständlich ist und wann es ok ist. Aus diesem Grund sollte ich vielleicht mal eine Perl-Schulung besuchen.

          Ich habe mir dein Statement nochmal genau durchgelesen und habe es zwar teilweise (!) verstanden, stehe aber doch ein wenig auf dem Schlauch. Ich werde es noch einmal etwas näher unter die Lupe nehmen, sobald ich ne Mütze voll Schlaf genommen hab!

          Vielen Dank!

          Mfg,
          Jonny

          1. Tag jonny.

            da ich ein absoluter Perl-Noob bin, weiß ich leider nie, wann es umständlich ist und wann es ok ist. Aus diesem Grund sollte ich vielleicht mal eine Perl-Schulung besuchen.

            Ich habe nie eine solche Schulung besucht, geschweige denn irgendwas in der Richtung studiert :-)

            Ich habe mir dein Statement nochmal genau durchgelesen und habe es zwar teilweise (!) verstanden, stehe aber doch ein wenig auf dem Schlauch. Ich werde es noch einmal etwas näher unter die Lupe nehmen, sobald ich ne Mütze voll Schlaf genommen hab!

            Frag ruhig nach, wenn dir noch was unklar ist.

            Siechfred

            --
            »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«
        2. Das soll doch hier sicher $tmp[$c] = "$tmp[$c]n$s"; heißen, oder?

          Sorry, natürlich. Sonst wäre der Index ja immer gleich.

          Mfg,
          Jonny

      2. Hallo,

        my $c=2;
        my @data0;
        my @data1;
        my @data2;
        my @data3;
        my @data4;
        my @data5;
        my $s=0;

        while(<FILE>) {
           my @tmp=split / /,$_;
           $tmp[$t]="$tmp[$t]n$t";  #n$t als Index
           $data0[$s]=$tmp[0];
           $data1[$s]=$tmp[1];
           $data2[$s]=$tmp[2];
           $data3[$s]=$tmp[3];
           $data4[$s]=$tmp[4];
           $data5[$s]=$tmp[5];
           $s++;
        }

        Du solltest Dir unbedingt einmal http://www.perldoc.com/perl5.8.4/pod/perldsc.html bzw. http://www.perldoc.com/perl5.8.4/pod/perllol.html

        Dann würde das ungefähr so aussehen (kann aber durchaus auhc abegwandelt werden;-)

        my $c=2;
        my @data;

        while(<FILE>) {
            my @tmp=split / /,$_;
            $tmp[$t]="$tmp[$t]n$t";  #n$t als Index
            for($col = 0; $col<6;$col++) {
               $data[$col][$s]=$tmp[$col];
               }
            $s++;
            }

        Und der Rest ist dann auch einfacher. Aber lies selbst.

        Grüße
          Klaus

        1. while(<FILE>) {
              my @tmp=split / /,$_;
              $tmp[$t]="$tmp[$t]n$t";  #n$t als Index
              for($col = 0; $col<6;$col++) {
                 $data[$col][$s]=$tmp[$col];
                 }

          Naja, ich hab das ja schon so ähnlich geschrieben:

          while(<FILE>) {
          push @data, [ split / /,$_ ];

          ...

          Das halte ich für lesbarer und ist mit Sicherheit auch schneller, was bei der Menge Daten um die es geht durchaus wichtig ist.

          Aber die Schwartzschen Transformation ist die beste Lösung.

          Struppi.

        2. Hi Klaus,

          den ersten der beiden Links habe ich schon durchgepaukt, der zweite folgt noch. Bisher wußte ich nichts von den mehrdimensionalen Arrays. Gut, jetzt weiß ich's :-)

          Danke.

          Mfg,
          Jonny

    2. Hallo Siechfred,

      jetzt starre ich nun schon seit ca. 1 1/2 Stunden auf diese drei Zeilen Code und versuche wirklich es zu verstehen.

      @sortiert = map  { $_->[0] }                                #1
                  sort { $a->[1] <=> $b->[1] }                    #2
                  map  { [ $_, (split / /)[$nr] ] } @zeilen;      #3

      Ich habe es folgendermaßen verstanden...

      zu 3.
      In $_ steht jede volle Zeile aus @zeilen, so wie es auch bei einem normalen Schleifendurchgang der Fall ist "while(<>) {}" und es werden anonyme Arrays gebildet [], genau genommen zwei, nämlich $a->[0] und $a->[1].

      zu 2.
      In $a->[0] befindet sich der Inhalt ausser $nr. In in $a->[1] befindet sich der Inhalt der split $nr Operation, also die Spalte, die ich sortieren möchte. Mit der Sortierung in $a->[1] wird auch die Reihenfolge der Zeilen in In $a->[0] angepasst.

      zu 1.
      wie du schon schriebst, wird hier das Ergebnis der Sortierung wieder an $_ zurückgegeben, also die sortierte Spalte wird wieder an ihre position gebracht.

      ???

      Mfg,
      Jonny

      1. Tag jonny.

        In $_ steht jede volle Zeile aus @zeilen, so wie es auch bei einem normalen Schleifendurchgang der Fall ist "while(<>) {}" und es werden anonyme Arrays gebildet [], genau genommen zwei, nämlich $a->[0] und $a->[1].

        Ich habe es mir bildlich als ein anonymes mehrdimensionales Array vorgestellt, also ein Array, dessen Elemente wiederum Arrays sind. Ich nehme mal die ersten zwei Zeilen aus deinem Ausgangsposting:

        Spalte 0   1    2    3  4  5
        ----------------------------
        20041215  2.3 812.2 48 32 20
        20041215 31.9  12.2 34 12 54

        Das letzte map macht daraus quasi ein anonymes mehrdimensionales Array:

        diesen Teil nenne ich »Elementarray«
                   ----------------------------------------------
        Liste[0] = [ Array[ Zeile 1, Spalte Nr. 3 aus Zeile 1 ] ]
                 = [ "20041215 2.3 812.2 48 32 20", "48" ]
        Liste[1] = [ Array[ Zeile 2, Spalte Nr. 3 aus Zeile 2 ] ]
                 = [ "20041215 31.9 12.2 34 12 54", "34" ]

        $a->[0] ist das erste Element des Elementarrays und hat die gesamte Zeile als Inhalt ($_), $a->[1] ist das zweite und hat nur das gesuchte Feld als Inhalt. Man könnte es auch so schreiben:

        $Liste[0][0] entspricht $a->[0] entspricht $_
        $Liste[0][1] entspricht $a->[1] entspricht dem Ergebnis der split-Anweisung

        Die Reihenfolge, in der die Elemente im Elementarray abgelegt werden, bestimmt die map-Anweisung.

        In $a->[0] befindet sich der Inhalt ausser $nr.

        Nein, die _komplette_ Zeile (repräsentiert durch $_), wie du oben siehst.

        In in $a->[1] befindet sich der Inhalt der split $nr Operation, also die Spalte, die ich sortieren möchte. Mit der Sortierung in $a->[1] wird auch die Reihenfolge der Zeilen in In $a->[0] angepasst.

        Genau, denn sortiert wird nicht das Elementarray »Array«, sondern »Liste«, Sortierkriterium ist dabei das zweite Element von »Array«, deshalb $a->[1].

        wie du schon schriebst, wird hier das Ergebnis der Sortierung wieder an $_ zurückgegeben, also die sortierte Spalte wird wieder an ihre position gebracht.

        Die anonyme Liste wird quasi aufgelöst, sodass am Ende vom nunmehr sortierten mehrdimensionalen anonymen Array nur ein einfacher Array »@sortiert« übrig bleibt, dessen Elemente jeweils eine vollständige Zeile enthalten, sortiert nach Spalte 3. $a->[1] wurde nur für die Sortierung benötigt und wird durch die obere map-Anweisung sozusagen eliminiert, da es nicht mehr gebraucht wird. Da diese map-Anweisung auf alle Listenelemente angewandt werden soll, muss die Liste Element für Element durchgegangen werden, deshalb kommt hier die vordefinierte Variable $_ (das jeweils aktuelle Element) zur Anwendung.

        Ich hoffe, dass ich mich einigermaßen verständlich ausgedrückt habe :-)

        Siechfred

        --
        »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«
        1. Hallo,

          schade, der Thread wandert bald ins Archiv, aber ich werde mich durch die 2. Beschreibung von euch (Siechfred, Struppi) nochmal durchbeissen. Das mit den zwei dimensionalen Arrays habe ich kapiert, der Rest kommt noch :-)

          Ich muss nur ein wenig Geduld mit mir selbst haben.

          Danke vielmals für Eure Hilfe !!!

          Bis zum nächsten Mal.

          Mfg,
          Jonny

          1. schade, der Thread wandert bald ins Archiv, aber ich werde mich durch die 2. Beschreibung von euch (Siechfred, Struppi) nochmal durchbeissen. Das mit den zwei dimensionalen Arrays habe ich kapiert, der Rest kommt noch :-)

            In Perl gibt es nicht wirklich 2 dimensonale Arrays, sondern du benutzt Arrays mit Referenzen auf Arrays (LoL).

            my @a;
            my @b = (1,2,3);
            mmy @c = (3,4,5);

            wenn du jetzt @a als erstes Element und @b als zweitest haben wolltest kannst du nicht:
            push @a, @b;
            push @a, @c;

            machen:

            print "$a[0]\n$a[1]";

            du erhälst einfach:
            1
            2

            die ersten beiden Elemente von @b

            @a ist jetzt: 1 2 3 4 5

            du musst Referenzen auf die arrays benutzen:

            push @a, @b;
            push @a, @c;

            print "$a[0]\n$a[1]";
            ARRAY(.....)
            ARRAY(.....)

            und kannst jetzt auf die Index von @b und @c zugreifen:

            print $a[0]->[2];
            3

            um auf die Arrays zugreifen zu können musst du diese zurückwandeln:

            foreach( @{ $a[0] } )
            {
            geht alle Elemente von @a durch
            }
            foreach( @{ $a[1] } )
            {
            geht alle Elemente von @b durch
            }

            Weitere Details findest du in den Docs.

            Struppi.

            1. Halli hallo Struppi,

              In Perl gibt es nicht wirklich 2 dimensonale Arrays, sondern du benutzt Arrays mit Referenzen auf Arrays (LoL).

              Klaus hatte mir einen Link zugeschickt, da sprach man von diesen zweidimensionalen Arrays, ich hatte nur den Sprachgebrauch angewandt.

              http://www.perldoc.com/perl5.8.4/pod/perldsc.html

              Da ich viel mit Graphiken arbeite (GD::Graph), ist mir diese Art und Zuweisung von Arrays schon aufgefallen @data=(@spalte0, @spalte1, @spalte3); nur wusste ich bisher nie, was das genau bedeutete. Jetzt weiß ich es :-)

              Ich komme mit meiner Entwicklung Tag für Tag besser voran, seit dem ich hier bei selfhtml meine Fragen stellen kann und kann auch viele meiner Skript professioneller umgestalten.

              Big thx!

              Mfg,
              Jonny

              1. Klaus hatte mir einen Link zugeschickt, da sprach man von diesen zweidimensionalen Arrays, ich hatte nur den Sprachgebrauch angewandt.

                http://www.perldoc.com/perl5.8.4/pod/perldsc.html

                The most important thing to understand about all data structures in Perl -- including multidimensional arrays--is that even though they might appear otherwise, Perl @ARRAYs and %HASHes are all internally one-dimensional. They can
                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
                hold only scalar values (meaning a string, number, or a reference). They cannot directly contain other arrays or hashes, but instead contain references to other arrays or hashes.

                Struppi.

                1. Tag Struppi.

                  [...] zweidimensionale Arrays [...]
                  The most important thing to understand about all data structures in Perl -- including multidimensional arrays--is that even though they might appear otherwise, Perl @ARRAYs and %HASHes are all internally one-dimensional. They can hold only scalar values (meaning a string, number, or a reference). They cannot directly contain other arrays or hashes, but instead contain references to other arrays or hashes.

                  Ich bin da wohl der Hauptschuldige, da ich in meiner zweiten Erklärung von einem zweidimensionalen Array schrieb, um das Ganze leichter nachvollziehbar zu gestalten. Aber natürlich hast du Recht :-)

                  Siechfred

                  --
                  »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«
                  1. nun ja, es hat allerdings den anschein eine 2da

                    Mfg,
                    Jonny

        2. Hallo Siechfred,

          Spalte 0   1    2    3  4  5

          20041215  2.3 812.2 48 32 20
          20041215 31.9  12.2 34 12 54

          »»

          also jetzt glaube ich es kapiert zu haben.

          ARRAY0                    ARRAY1
                   Spalte 0   1    2    3  4  5           3
                   ----------------------------        ------
          ARRAY0   20041215  2.3 812.2 48 32 20    $nr   48
          ARRAY0   20041215 31.9  12.2 34 12 54    $nr   34

          ARRAY0 ist Liste[0], Liste[1] ... die zweite Liste, also ARRAY1, wird dran gehängt ... Liste[0][0], Liste[1][1]

          Beides ergibt das sogannte zweidimensionale Array, was jedoch nur eine Referenz auf ein anderes Array ist (@), also auf das Array, dass sortiert werden soll.

          Also anders ausgedrückt:

          ARRAY0 = $a->[0]
          ARRAY1 = $a->[1]

          Die Splittung in beide anonyme Arrays erfolgt in der dritten Zeile:

          map  { [ $_, (split / /)[$nr] ] } @zeilen;

          $_ enthält die ganze Zeile, wie es sich für einen Schleifendurchgang gehört, mit split / / wird die Zeile aufgeteilt und Spalte $nr "herauskopiert", $_ wird in $a->[0] abgelegt, $nr in $a->[1].

          line1=echo $line0 | cut -d' ' -f4   # :-)

          Ich hoffe, dass ich mich einigermaßen verständlich ausgedrückt habe :-)

          Wenn an meiner Interpretierung nichts auszusetzen ist, habe ich es verstanden.

          Super !!!

          Mfg,
          Jonny

          1. Tag jonny.

            also jetzt glaube ich es kapiert zu haben.
            [...]

            Siehst du, war doch gar nicht so schwierig :-)

            Wenn an meiner Interpretierung nichts auszusetzen ist, habe ich es verstanden.

            Damit hättest du meine 2 Lichtjahre getoppt ;-)

            Siechfred

            --
            »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«
            1. Damit hättest du meine 2 Lichtjahre getoppt ;-)

              Schön wärs! Ohne Eure Hilfe säße ich noch immer auf 'nem Schlauch :-)

              Sobald der Thread ins Archiv gewandert ist, könnte es nochmal vorkommen, dass ich Fragen habe, da ich derzeit ein wenig erfolglos am Testen bin. Dann mache ich nochmal einen Thread auf, wenn's ok ist.

              Mfg,
              Jonny

      2. Hallo jonny

        Hallo Siechfred,

        jetzt starre ich nun schon seit ca. 1 1/2 Stunden auf diese drei Zeilen Code und versuche wirklich es zu verstehen.

        @sortiert = map  { $_->[0] }                                #1
                    sort { $a->[1] <=> $b->[1] }                    #2
                    map  { [ $_, (split / /)[$nr] ] } @zeilen;      #3

        Ich habe es folgendermaßen verstanden...

        zu 3.
        In $_ steht jede volle Zeile aus @zeilen, so wie es auch bei einem normalen Schleifendurchgang der Fall ist "while(<>) {}" und es werden anonyme Arrays gebildet [], genau genommen zwei, nämlich $a->[0] und $a->[1].

        Nein, ein Array. Index [0] ist die Zeile und [1] ist die Spalten nach der du sortieren willst.
        (es ist übrigens eher eine foreach Schleife als while)

        zu 2.
        In $a->[0] befindet sich der Inhalt ausser $nr. In in $a->[1] befindet sich der Inhalt der split $nr Operation, also die Spalte, die ich sortieren möchte. Mit der Sortierung in $a->[1] wird auch die Reihenfolge der Zeilen in In $a->[0] angepasst.

        In $a->[0] und $b->[0] ist jeweils die komplette Zeile. In [1] ist die Spalte, richtig. Mit 2.) wird das Array (mit den anonymen Array als einträge) das in 1.) (mit dem map) erzeugt wird sortiert.

        zu 1.
        wie du schon schriebst, wird hier das Ergebnis der Sortierung wieder an $_ zurückgegeben, also die sortierte Spalte wird wieder an ihre position gebracht.

        Nein, es werden die ursprüngliche Zeilen sortiert nach n zurückgegeben.

        Das ganze ist ungefähr das gleiche wie ich dir hier schon schrieb https://forum.selfhtml.org/?t=99696&m=609398 wobei das von mir aber ein bisschen verständlicher ist als die Schwartzschen Transformation, wie ich finde.

        Struppi.

    3. @sortiert = map  { $_->[0] }
                  sort { $a->[1] <=> $b->[1] }
                  map  { [ $_, (split / /)[$nr] ] } @zeilen;

      Hallo Siechfred,
      ich weiß zwar was timtdi und wer Larry Wall ist, aber damit hat es sich dann auch schon mit meinen Perl-Kenntnissen. Würde die o.g. Transformation auch in Javascript funktionieren? (Ich bin allerdings nicht sicher, ob es da anomyme Arrays gibt)

      Viele Grüße,
      Konrad

      1. Tag Konrad.

        Würde die o.g. Transformation auch in Javascript funktionieren? (Ich bin allerdings nicht sicher, ob es da anomyme Arrays gibt)

        Naja, es dürfte m.E. ziemlich schwierig sein, die Schwartzsche Transformation in Javascript umzusetzen. Prinzipiell kann man allerdings Array.sort auch auf mehrdimensionale Arrays anwenden:

        <script  type="text/javascript">
        <!--
        function Numsort(a,b)
        { return a[nr]-b[nr]; }

        var Namen = new Array();
        // Name des Dichters, Geburtsjahr, Sterbejahr, Alter
        Namen[0] = ["Friedrich Schiller",1759,1805,46];
        Namen[1] = ["Johann Wolfgang Goethe",1749,1832,83];
        Namen[2] = ["Bettina von Arnim",1785,1859,74];
        Namen[3] = ["Clemens Brentano",1778,1842,64];

        var nr=1;
        Namen.sort(Numsort);
        Namenausgabe = Namen.join("<br>");
        document.write("<p>Nach Geburtsjahr sortierte Namen:<br>" + Namenausgabe + "</p>");

        var nr=2;
        Namen.sort(Numsort);
        Namenausgabe = Namen.join("<br>");
        document.write("<p>Nach Sterbejahr sortierte Namen:<br>" + Namenausgabe + "</p>");

        var nr=3;
        Namen.sort(Numsort);
        Namenausgabe = Namen.join("<br>");
        document.write("<p>Nach erreichtem Lebensalter sortierte Namen:<br>" + Namenausgabe + "</p>");

        //-->
        </script>

        Allerdings funktioniert das mit Numsort nur bei Zahlen, nicht aber bei Strings, die nicht nur aus Zahlen bestehen. Würde man in meinem obigen Beispiel Numsort auf Spalte 0 anwenden, führt das nicht zu einem brauchbaren Ergebnis.

        Siechfred

        --
        »Sie kochten heimlich mit Wasser und tranken öffentlich Wein.«