speedy: Sortieralgorithmus

Hi Forumers,

gibt es eine Möglichkeit, die sort-Funktion in PERL so zu beeinflussen, daß sie String mit enthaltenen Zahlen richtig sortiert (also nach der Wertigkeit der Zahlen). Etwa nach folgendem Beispiel:

RAWLIST: name14, name1, name65, name100

SORTLIST: name1, name14, name65, name100

Vielen Dank für Eure Hilfe
  speedy

  1. Hallo!

    gibt es eine Möglichkeit, die sort-Funktion in PERL so zu beeinflussen, daß sie String mit enthaltenen Zahlen richtig sortiert (also nach der Wertigkeit der Zahlen). Etwa nach folgendem Beispiel:
    RAWLIST: name14, name1, name65, name100
    SORTLIST: name1, name14, name65, name100

    Soll das Prefix ("name") immer gleich sein?
    In diesem Falle würde ich sprintf verwenden (z.B. $a = sprintf ("%03d", $a); ), um etwas in der Form name014, name015 zu erhalten.
    Und dann kannst Du mit @sort_list = sort (@unsort_list); das ganze einfach sortieren. (ev. noch reverse anwenden, um die gewünschte Reihenfolge zu erhalten.)
    Ist das Präfix nicht gleich, würde ich mit hashes arbeiten.

    Felix

  2. hi ho

    @sortlist=sort {my $x=$a,$y=$b;$x=~s/\D*//;$y=~s/\D*//;$x<=>$y;} @rawlist

    tut genau das, was du moechtest :-)
    und zwar loescht er aus dem string alles bis zur ersten ziffer ($x=~s/\D*//)
    und vergleicht dann die ziffern ($x<=>$y)

    ich liebe einzeiler :-)

    cua

    n.d.p.

    1. hi ho

      @sortlist=sort {my $x=$a,$y=$b;$x=~s/\D*//;$y=~s/\D*//;$x<=>$y;} @rawlist

      tut genau das, was du moechtest :-)
      und zwar loescht er aus dem string alles bis zur ersten ziffer ($x=~s/\D*//)
      und vergleicht dann die ziffern ($x<=>$y)

      ich liebe einzeiler :-)

      ;-)))) s.u.

      Ich bin mir da nicht so sicher, daß Deine Lösung genau das Richtige tut ... Ich habe es zumindest so verstanden, daß die Strings nicht einfach ignoriert werden sollten:
      @rawlist = qw(name7 name100 name7ort50 name7strasse name7abc name15hallo9 name100ok name7ort1000 name);
      sollte wohl folgendes ergeben:
        name
        name7
        name7abc
        name7ort50
        name7ort1000
        name7strasse
        name15hallo9
        name100
        name100ok

      Mein Einzeiler dazu:

      @sortlist=sort{my(@b,$r)=split'(\d+)',$b;for(split'(\d+)',$a){$r=/\d/?$_<=>shift@b :$_ cmp shift@b}$r-@b} @rawlist;

      Ist ja recht grausam ... besser wäre da wohl:
      -----------------------------------------------------------------------------
      sub numbercmp {
        # die split-Funktion erzeugt eine Liste, in
        # der abwechselnd Texte und Zahlen auftreten

      my (@b, $result, $a_part, $b_part) = split('(\d+)', $b);

      #-----------------------------------------------
        # Nun wird jeder Listenteil des Parameters $a
        # mit dem entsprechenden Teil von $b verglichen

      foreach $a_part (split('(\d+)', $a)) {

      #----------------------------------------------------
          # Der entsprechende Teil von $b wird besorgt, in dem
          # das entprechende Array von vorne gekürzt wird
          
          $b_part = shift(@b);

      #--------------------------------------------------
          # Sind die Teile Zahlen, dann mit <=> vergleichen.
          # Sonst mit cmp
          # Enthält $result schon einen Wert ungleich null,
          # so ergab ein früherer Durchlauf ein Ergebnis.
          # Dann muss nicht weiter verglichen werden (=)
          
          if ($a_part =~ m/\d/) {
            $result = $result $a_part <=> $b_part;
          } else {
            $result = $result $a_part cmp $b_part;
          }
        }

      #-----------------------------------------------
        # Ist hier $result noch null, dann waren bisher
        # alle Vergleiche ergebnislos. Ist im Array zu
        # $b noch Inhalt, so ist $a der kleinere
        
        unless ($result) {
          $result = -1 if @b;
        }
        return $result;
      }

      print join "\n", sort numbercmp @rawlist;
      -----------------------------------------------------------------------------

      Viel Spaß,
         Jörk