I'm trying to write a sort function in Perl. I need "name_iwant_last" to be the last in a sorted hash.
%libs = (
"00000000000","00000000000",
"aaaaaaaaaaa","aaaaaaaaaaa",
"AAAAAAAAAA","AAAAAAAAAA",
"name_iwant_last","name_iwant_last",
"zzzzzzzzzzzzz","zzzzzzzzzzzzz",
"ZZZZZZZZZZZ","ZZZZZZZZZZZ",
"9999999999","9999999999"
);
sub lib_sort {
#print "cosa ordino ";
#print $libs{$a};
#print $libs{$b};
#print "\n";
return 1 if (index($libs{$a} , "name_iwant_last") != -1);
return -1 if $libs{$a} < $libs{$b};
return 0 if $libs{$a} == $libs{$b};
return 1 if $libs{$a} > $libs{$b};
}
foreach my $lib (sort lib_sort values %libs) {
print $lib;
print "\n";
}
But, when I run this code, the print is in random order.
Expected:
aaaaa
AAAAA...
name_iwant_last
Resulted: random.
CodePudding user response:
If you add use warnings
to your code, then you'll see a few warnings like this:
Argument "ZZZZZZZZZZZ" isn't numeric in numeric lt (<) at sort line 20.
Argument "AAAAAAAAAA" isn't numeric in numeric lt (<) at sort line 20.
Argument "zzzzzzzzzzzzz" isn't numeric in numeric lt (<) at sort line 20.
Argument "aaaaaaaaaaa" isn't numeric in numeric lt (<) at sort line 20.
Argument "name_iwant_last" isn't numeric in numeric lt (<) at sort line 20.
You're comparing strings, but you're using the numeric comparison operators (<
, ==
, >
). If you switch to using string comparison operators (lt
, eq
, gt
) then it will work as expected.
And always have use warnings
and use strict
in your code.
Update: As discussed in the comments, a better way to write this is to use cmp
(which is the string comparison version of <=>
).
sub lib_sort {
return 1 if (index($libs{$a} , "name_iwant_last") != -1);
return -$libs{$a} cmp $libs{$b};
}
CodePudding user response:
A working version of my code:
%libs = (
"00000000000","00000000000",
"aaaaaaaaaaa","aaaaaaaaaaa",
"AAAAAAAAAA","AAAAAAAAAA",
"name_iwant_last","name_iwant_last",
"zzzzzzzzzzzzz","zzzzzzzzzzzzz",
"ZZZZZZZZZZZ","ZZZZZZZZZZZ",
"9999999999","9999999999"
);
sub lib_sort {
#print "cosa ordino ";
#print $libs{$a};
#print $libs{$b};
#print "\n";
if (index($libs{$a} , "name_iwant_last") != -1) {
return 1;
} elsif (index($libs{$b} , "name_iwant_last") != -1) {
return -1;
} elsif ($libs{$a} lt $libs{$b}) {
return -1;
} elsif ($libs{$a} eq $libs{$b}) {
return 0;
} elsif ($libs{$a} gt $libs{$b}) {
return 1;
}
}
foreach my $lib (sort lib_sort values %libs) {
print $lib;
print "\n";
}