Reputation: 1360
I am trying to learn to sort a 2D array in perl by multiple columns so that the values are sorted in the order in which columns are specified, that is, first sort according to first column, then according to the second column etc. So that the table:
3 2
5 2
1 4
is sorted to
1 4
3 2
5 2
if the sort is in the order first column, second column or to
3 2
5 2
1 4
if the sort is according to the second column and then the first.
But it turns out I cannot even sort the table according to any column.
my @a = ([3,1,2], [3,5,4]);
my @b = sort {
$a->[0] <=> $b->[0]
} @a;
print Dumper \@b
Does not do anything. Where am I making the mistake and how to achieve the above mentioned sort in proper column order?
Upvotes: 1
Views: 667
Reputation: 117298
I'm reading my @a = ([3,1,2], [3,5,4]);
as it has 2 rows with 3 columns each. I'd store the table
3 3
1 5
2 4
as my @a = ([3, 3], [1, 5], [2, 4]);
instead, which makes sorting simpler by using Short-circuit evaluation:
my @a = ([3, 3], [1, 5], [2, 4]);
my @b = sort {
# Short-circuit evaluation:
# if the values in the first column aren't equal, return the <=> result for
# that, otherwise return the <=> result for the second column
$a->[0] <=> $b->[0] || $a->[1] <=> $b->[1];
} @a;
# @b is now ([1, 5], [2, 4], [3, 3])
Upvotes: 2
Reputation: 86774
You are sorting, just not the way you think you are. @a
contains two objects, both array references. You are sorting those two references by the value of the first element in each referenced array.
Consider the following, using your example data:
@array = ([3,2],[5,2],[1,4]);
@sorted_01 = sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @array;
@sorted_10 = sort { $a->[1] <=> $b->[1] || $a->[0] <=> $b->[0] } @array;
The construct a<=>b || c<=>d
compares a
and b
. If the result is non-zero (i.e. a
and b
are not equal) the expression evaluation ends. If they are equal however, evaluation continues and returns the result of comparing c
and d
.
Upvotes: 1
Reputation: 385789
Your code actually works.
The are passing to scalars two sort
, the results of [3,1,2]
and [3,5,4]
. Then you sort these two elements based on the element of the referenced array ($a->[0] <=> $b->[0]
). Why doesn't do anything? Well, because those arrays have the same value (3
) as their first element.
If you the referenced arrays had different values in the first column (say [6,1,2]
and [3,5,4]
), you the one with the lowest value would have been returned first ([3,5,4]
then [6,1,2]
).
Upvotes: 1