我有一些代码可以使用,但是会发出很多警告。
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,我希望我的代码更强大。
由于
答案 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) {
...