What you need to do is to put the numbers into a structure that can be sorted
while keeping track of the positions of the values in the original 2D array.
A hash is ideal for this, store the array indexes as an anonymous array in
the hash value. Then sort on the hash key and that will give you the rank.
This was my first attempt:
use warnings;
use strict;
my @total;
$total[1][1] = 123;
$total[2][1] = 345;
$total[3][1] = 222;
# hash of arrays: hash{ number } = [ i, j ]
my %hash;
for my $i ( 1 .. $#total ) {
for my $j ( 1 .. $#{$total[$i]} ) {
$hash{ $total[$i][$j] } = [ $i, $j ];
}
}
my @rank;
my $ranking = 0;
foreach my $value ( sort keys %hash ){
my ( $i, $j ) = @{$hash{ $value }};
$rank[$i][$j] = ++$ranking;
}
for my $i ( 1 .. $#rank ) {
for my $j ( 1 .. $#{$rank[$i]} ) {
print "rank[$i][$j] is $rank[$i][$j]\n";
}
}
and here is the output:
rank[1][1] is 1
rank[2][1] is 3
rank[3][1] is 2
But then I realised that this won't work if a value appears more than once: the
hash element is overwritten. We need a little more intelligence, here's my second attempt:
use warnings;
use strict;
my @total;
$total[1][1] = 123;
$total[2][1] = 345;
$total[3][1] = 222;
$total[4][1] = 222;
# hash of arrays: hash{ number } = [ i, j ]
my %hash;
for my $i ( 1 .. $#total ) {
for my $j ( 1 .. $#{$total[$i]} ) {
push @{$hash{ $total[$i][$j] }}, $i, $j;
}
}
my @rank;
my $ranking = 0;
foreach my $value ( sort keys %hash ){
++$ranking;
while ( my ($i, $j ) = splice @{$hash{ $value }}, 0, 2 ){
$rank[$i][$j] = $ranking;
}
}
for my $i ( 1 .. $#rank ) {
for my $j ( 1 .. $#{$rank[$i]} ) {
print "rank[$i][$j] is $rank[$i][$j]\n";
}
}
which gives:
rank[1][1] is 1
rank[2][1] is 3
rank[3][1] is 2
rank[4][1] is 2
As an aside, you are the second poster today I have seen starting arrays at 1 - doing this
is a bit confusing, and also you still get $array[0] created automatically and set to undef.
This then gives you extra values if you do something like print @array.
--
iakobski |