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 ]
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 ]
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 ]