I have an array of arrays that I want to sort. Each element of array A is an array with 3 elements. Array A looks like:
my @A = ([2,3,1], [1,2,3], [1,0,2], [3,1,2], [2,2,4]);
I want to sort A in ascending order. When comparing 2 elements, the first number is used. If there is a tie, the second number is used, and then the third number.
Here is my code. I use a function 'cmpfunc' to compare 2 elements.
sub cmpfunc {
return ($a->[0] <=> $b->[0]) or
($a->[1] <=> $b->[1]) or
($a->[2] <=> $b->[2]);
}
my @B = sort cmpfunc @A;
print "Result:\n";
for my $element (@B) {
print join(",", @{$element}) . "\n";
}
Result:
1,2,3
1,0,2
2,3,1
2,2,4
3,1,2
The result is somewhat sorted, but not correct. What I expect is:
1,0,2
1,2,3
2,2,4
2,3,1
3,1,2
Is there any error in my comparison function? The strange thing is, when I put the comparison code in block, the result is correctly sorted.
my @C = sort { ($a->[0] <=> $b->[0]) or
($a->[1] <=> $b->[1]) or
($a->[2] <=> $b->[2]) } @A;
Perl has a built-in sort() function to sort an array of alphabets and numbers. When an array is passed to the sort() function it returns a sorted array. Sorting of Arrays in Perl can be done in multiple ways: Use of ASCII values to sort an Array.
If you use the native array sort function, you can pass in a custom comparator to be used when sorting the array. The comparator should return a negative number if the first value is less than the second, zero if they're equal, and a positive number if the first value is greater.
Arrays. sort() method can be used to sort a subset of the array elements in Java. This method has three arguments i.e. the array to be sorted, the index of the first element of the subset (included in the sorted elements) and the index of the last element of the subset (excluded from the sorted elements).
You are executing
return ($a->[0] <=> $b->[0])
which returns before it gets to any of the "or" clauses.
Either remove the "return" keyword, or add parenthesis around the entire arg list for return:
sub cmpfunc {
return(($a->[0] <=> $b->[0]) or
($a->[1] <=> $b->[1]) or
($a->[2] <=> $b->[2]));
}
The reason you observe this "wrong" behavior is the priority of or
operator, the lowest possible. In this situation it means that
return ($a->[0] <=> $b->[0]) or
($a->[1] <=> $b->[1]) or
($a->[2] <=> $b->[2]);
is interpreted as OR-ing
return ($a->[0] <=> $b->[0])
and the rest of the line -- nonsense in this case, as return never returns. :)
So you should use C's OR:
return ($a->[0] <=> $b->[0]) ||
($a->[1] <=> $b->[1]) ||
($a->[2] <=> $b->[2]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With