Jörk Behrends: Sortieralgorithmus

Beitrag lesen

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