我需要Perl代码来将一个数组中的数字排列到另一个数组中而不对其进行排序。因此,输入:(10,4,2,9,32)=>输出:(4,2,1,3,5)
我的代码很接近,但是我发现它没用,因为输入和输出不完全是我想要的:
use strict;
use warnings;
use Data::Dumper;
my %data =
(
1 => 10,
2 => 4,
3 => 2,
4 => 9,
5 => 32,
);
my ($n, @rank) = 1;
foreach( keys %data){
$rank[ $data{$_} ] .= "$_ ";
}
defined and $n += print for @rank;
上面的代码输出:
3 2 4 1 5
输出是错误的,顺便说一句,输出根本不是必需的,我只希望将结果数组@rank用作所述的1D数组。最好在不将键分配给输入数组数据的情况下。
答案 0 :(得分:3)
这是我的解决方法:
use strict;
use warnings;
my @numbers = (10, 4, 2, 9, 32);
my %rank_of;
@rank_of{sort { $a <=> $b } @numbers} = 1 .. @numbers;
print join(" ", map $rank_of{$_}, @numbers), "\n";
我们构造了一个散列,将每个数字映射到其对应的等级,然后按照原始数组的顺序打印每个数字的等级。
我们通过将每个数字(按排序顺序)与列表1、2、3,...配对来计算等级,即:
2 4 9 10 32 # sort { $a <=> $b } @numbers
| | | | |
1 2 3 4 5 # 1 .. @numbers
答案 1 :(得分:1)
您可以分两步执行此操作,首先对数组的索引排序,然后对这些索引的索引排序以获得(从0开始)排名,再加一个以获得从1开始的排名。
my @array = (10, 4, 2, 9, 32);
my @index_by_rank_minus_1 = sort { $array[$a] <=> $array[$b] } 0..$#array;
my @ranks =
map $_+1,
sort { $index_by_rank_minus_1[$a] <=> $index_by_rank_minus_1[$b] } 0..$#array;
或者,以下内容可能会更快一些(尽管它可能仅对很长的列表才有意义)。
my @array = (10, 4, 2, 9, 32);
my %rank_by_index;
@rank_by_index{ sort { $array[$a] <=> $array[$b] } 0..$#array } = 1..@array;
my @ranks = map { $rank_by_index{$_} } 0..$#array;