【问题标题】:Perl: Rank but don't sort 1D arrayPerl:排名但不排序一维数组
【发布时间】:2019-03-30 11:24:29
【问题描述】:

我需要 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 像描述的那样作为一维数组。如果可以不将键分配给输入数组数据,则最好。

【问题讨论】:

    标签: arrays perl rank


    【解决方案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;
    

    【讨论】:

    • 完美!谢谢
    • 重复的值被分配不同的等级!
    【解决方案2】:

    这是我的解决方案:

    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
    

    【讨论】:

    • 如果有重复,可能无法正常工作
    • 有趣的解决方案。我会保存它,因为我以后可能需要一些变化,但我想我会使用 @ysth 的解决方案来解决这个特定问题。
    • @ysth,使用此解决方案,相同的值获得相同的排名。这似乎比相反更合适。
    猜你喜欢
    • 1970-01-01
    • 2016-08-07
    • 2012-04-24
    • 1970-01-01
    • 2012-03-11
    • 2018-07-11
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多