in reply to Sorting issues
which produced the following output:#!/usr/local/bin/perl -w use strict; my @database = <DATA>; my @sorted=sort{my $one=substr($a,rindex($a,'|')); my $two=substr($b,rindex($b,'|')); ($one <=> $two) } @database; print @sorted; __DATA__ a|b|c|10 d|e|f|100 g|h|i|2
The warnings reveal the problem quite conveniently; the substr() is including the pipe character, so all the values being compared are numerically equal to zero and thus to each other.Argument "|10\n" isn't numeric in ncmp at tmp.pl line 9, <DATA> chunk +3. Argument "|100\n" isn't numeric in ncmp at tmp.pl line 9, <DATA> chunk + 3. Argument "|100\n" isn't numeric in ncmp at tmp.pl line 9, <DATA> chunk + 3. Argument "|2\n" isn't numeric in ncmp at tmp.pl line 9, <DATA> chunk 3 +. a|b|c|10 d|e|f|100 g|h|i|2
You can easily fix this error by adding 1 to each rindex(). However, I would suggest making another change as well. You're doing a fair amount of work in the sort subroutine, which makes it inefficient. A Schwartzian Transform moves the work out of the sort sub:
my @sorted = map $_->[1], sort { $a->[0] <=> $b->[0] } map [ substr($_,rindex($_,'|')+1), $_ ], @database;
But, there's another option that would work well here, and should be even more efficient because it uses an optimized sort sub. This one is often called the Guttman-Rosler Transform:
As you can see, this is very similar to the Schwartzian Transform, but the intermediate value is a string instead of an anonymous array.my $width = 10; # must be at least as big as the longest field being +compared my @sorted = map substr($_, index($_, '|')+1), sort map sprintf("%0${width}d|%s", substr($_,rindex($_,'|')+1) +, $_), @database;
|
|---|