perl最大标量值

时间:2012-06-06 14:50:11

标签: perl

我有一些代码可以使用,但是会发出很多警告。

    foreach my $item ( sort {$item_rank{$a} <=> $item_rank{$b}} @items{
        ...
    }

我的问题是并非每个项目都有排名,因此我的输出中充斥着警告。我想最后没有排名的项目。 我正在考虑将代码更改为:

    foreach my $item ( sort {
                              $item_rank{$a} = 99999 if(!exist $item_rank{$a});
                              $item_rank{$b} = 99999 if(!exist $item_rank{$b});
                              $item_rank{$a} <=> $item_rank{$b}} @items{
        ...
    }

我的问题是,是否有一个特定的值我可以设置它而不是99999,虽然在我当前的设置中我永远不会达到99999,我希望我的代码更强大。

由于

2 个答案:

答案 0 :(得分:4)

您可以采用以下两种方式之一:

  • 如果您已定义最大上限,则默认为它(为了简化代码,我假设0不是有效等级)

    $max_ceiling = 99999;
    sort { ($item_rank{$a} || $max_ceiling)
       <=> ($item_rank{$b} || $max_ceiling) } @items
    

    或者,为了避免分配哈希:

    # Ideally, %item_rank should be passed as a parameter but meh.
    sub rank4comp { exist $item_rank{$_[0]} ? $item_rank{$_[0]} : 999999; }
    sort { rank4comp($a) <=> rank4comp($b) } @items;
    
  • 更好的是,在表达式中明确检查undefs (请记住sort's code block可以是ANY表达式,返回负数,0或正数ala“<=> “:

    sort { defined $item_rank{$a}
         ? defined $item_rank{$b}
         ? $item_rank{$a} <=> $item_rank{$b} : 1 : -1 } @items;
    

答案 1 :(得分:3)

由于您对未记录的记录的标准有明确的定义,您可以将这两个组分开:

my @unranked = grep ! defined($item_rank{$_}), keys %item_rank;
my @ranked   = grep   defined($item_rank{$_}), keys %item_rank;

然后您可以按照惯例进行排序,甚至可以将两个数组包含在同一个for循环中:

for my $item (sort ( { $item_rank{$a} <=> $item_rank{$b} } @ranked), @unranked) {
    print "$item => ", $item_rank{$item} // "N/A", "\n";
}

这将自动将所有未排名的项目放在最后。

请注意,您需要围绕sort的参数进行调整,以避免@unranked的元素成为sort的参数的一部分。我使用defined-or运算符//来检查print语句中的未定义值。

您甚至可以将排序移至grep语句:

my @unranked = grep ! defined($item_rank{$_}), keys %item_rank;
my @ranked   = sort { $item_rank{$a} <=> $item_rank{$b} }
                   grep defined($item_rank{$_}), keys %item_rank;

for my $item (@ranked, @unranked) { 
...