You may be making a mistake if there are undefs in your hash. That warning is telling you something. If you don't mind that undef and zero (0) get sorted as the same value, you have nothing to worry about with rata's solution, and the warnings can be ignored. But if undef should be ordered differently from zero, you need to do an additional check.
Please have a look at the following test code that demonstrates three ways to handle your sort, while also dealing with the warnings.
use 5.012_002; use strict; use warnings; my %hash = ( this => 1, that => 4, the => undef, other => undef, those => 2, it => 0, ); # First simply disable the warning temporarily. { no warnings qw/uninitialized/; my @warnsorted = sort { $hash{$a} <=> $hash{$b} } keys %hash; say "Without Warnings:\t@warnsorted"; } # Second, check each item for definedness. my @defsorted = sort { ( defined( $hash{$a} ) && $hash{$a} ) <=> ( defined( $hash{$b} ) && $hash{$b} ) } keys %hash; say "Testing Definedness:\t@defsorted"; # Third, sort with definedness as a criteria my @critsorted = sort { defined( $hash{$a} ) <=> defined( $hash{$b} ) or ( defined( $hash{$a} ) && $hash{$a} ) <=> ( defined( $hash{$b} ) && $hash{$b} ) } keys %hash; say "Defined as Criteria:\t@critsorted";
And the output:
Without Warnings: the it other this those that Testing Definedness: the it other this those that Defined as Criteria: the other it this those that
The first method shown simply disables the warning, lexically scoped to a very narrow scope surrounding the sort. But this doesn't deal with the fact that 'undef' and '0' will get sorted together as the same effective value.
The second method eliminates the warning by not directly sorting undefs. What it does is test each side of the comparison for definedness. If defined, then compare the value on that side of the <=>. If undefined, compare the value returned by defined(), which would be zero in that case. This preserves the possibly errant artifact of undef being comparatively the same as zero.
The third method first does a definedness comparison on both sides of the <=>. If those are equal, then it moves on to a regular sort similar to my second example. This method will promote undef to the top of the heap, above '0'. Of course you could demote it to the bottom of the pile just as easily. But the point is that it sorts undef as a value different from zero.
There's a final solution which reduces the number of calls to defined, by combining the first method with the third:
{ no warnings qw/uninitialized/; my @sorted = sort { defined( $hash{$a} ) <=> defined( $hash{$b} ) or $hash{$a} <=> $hash{$b} } keys %hash; say "Defined as Criteria:\t@sorted"; }
Here we are still sorting with undef as a distinctly different value from zero, but warnings would continue to be generated. Since we're already sure that we've dealt with that warning, it would be safe to just ignore it, which is what the no warnings...... does for us.
Dave
In reply to Re^3: Sorting an array of hashes by a value of hash
by davido
in thread Sorting an array of hashes by a value of hash
by simonozzy
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |