Home : Website : Perl :

Sorting


Numerical Sort on Text

I had to sort text keys based on the numbers at the beginning of the string. While a numerical sort would work, it was dumping a bunch of warnings. I found a solution on the perldoc.perl.org sort page. They had an example that was almost exactly what I needed. The important part is the /^(\d+)/, which sets it up to sort on integers found at the start of the string.

    @new = map { $_->[0] }
          sort { $b->[1] <=> $a->[1]
                           ||
                  $a->[2] cmp $b->[2]
          } map { [$_, /^(\d+)/, uc($_)] } @old;

...simplified for my needs, 'or' text sort removed.

foreach my $key (map {$_->[0]} sort {$b->[1] <=> $a->[1]} map {[$_, /^(\d+)/]} keys %found) {
   print $found{$key};
}

Probably a lousy explanation: $_ = [0] and /^(\d+)/ = [1], [0] is $key and sort is based on [1].
[ comment | link | top ]admin

Sorting a flatfile db

While reading the db (RDB) I build a hash using 2 fields for the keys and the records (lines/$_) for the values. I want to alphabetically sort the db on the 3rd field ($rec[2]). Because more than one record can have the same data in this field I also added the record id field ($rec[0]) to the key (the space between them is important). The hash is sorted and written to WDB (which is closed and renamed RDB before RDB is closed).

while (RDB){
   my @rec = split(/\|/,$_);
   $rhash{"$rec[2] $rec[0]"} = $_;
}
foreach my $key (sort {lc($a) cmp lc($b)} keys %rhash) {
   print WDB $rhash{$key};
}

[ comment | link | top ]admin

Sorting an array based on a string match

In this case I'm sorting an array (@links) based on paths enclosed in comments (<!--foo/bar/baz-->). I create a hash with the paths as the keys and the full strings as values. I sort the hash (keys/paths) and push the sorted values (strings) into another array (@slinks).

my %lhash = ();
foreach my $link (@links) {
   $link=~m|^(.+)<!--(\w+.*)-->.*|;
   $lhash{$2} = "$1<!--$2-->";
}
foreach my $key (sort {lc($a) cmp lc($b)} keys %lhash) {
   push (@slinks, $lhash{$key})
}

[ comment | link | top ]admin

Back to: Perl