我有一个哈希,我按照从大到小的值进行排序。我该如何进入前五名?这里有一篇关于只获取一个值的帖子。
在Perl中,从散列中获得具有最高值的密钥的最简单方法是什么?
我理解这一点,比如说,获取这些值将它们添加到数组中,删除哈希中的元素,然后重新执行该过程?
看起来应该有一个更简单的方法来做这件事然后。
我的哈希叫做%words。
编辑取出代码作为问题的答案,而不需要它。
您的问题是如何从哈希中获得五个最高值。你有这个代码:
my @keys = sort {
$words{$b} <=> $words{$a}
or
"L$a" cmp "L$b"
} keys %words;
您已排序的哈希键所在的位置。从那里拿走五把最上面的钥匙?
my @highest = splice @keys, 0, 5; # also deletes the keys from the array
my @highest = @keys[0..4]; # non-destructive solution
还有一些关于你的代码的评论:
open( my $filehandle0, '<', $file0 ) || die "Could not open $file0n";
最好在die语句中包含错误消息$!
,以获取打开失败原因的有价值信息。
for (@words) {
s/[,|.|!|?|:|;|"]//g;
}
正如我在评论中所说,您不需要转义字符或在字符类括号中使用替换。使用任一:
s/[,.!?:;"]//g for @words; #or
tr/,.!?:;"//d for @words;
下一部分有点奇怪。
my @stopwords;
while ( my $line = <$filehandle1> ) {
chomp $line;
my @linearray = split( " ", $line );
push( @stopwords, @linearray );
}
for my $w ( my @stopwords ) {
s/bQ$wEB//ig;
}
你从文件中读到了停止语。。。然后从$_
中删除停止语?此时您是否正在使用$_
?此外,您正在循环头中重新声明@stopwords
数组,这实际上意味着您的新数组将为空,并且您的循环将永远不会运行。这个错误似乎是无声的,所以你可能永远不会注意到。
my %words = %words_count;
在这里,您制作了一个%words_count
的副本,它似乎是多余的,因为您再也不用它了。如果你有一个大散列,这可能会降低性能。
my $key_count = 0;
$key_count = keys %words;
这可以在一行中完成:my $key_count = keys %words
。在我看来,可读性更强。
$value_count = $words{$key} + $value_count;
也可以缩写为+=
运算符:$value_cont += $words{$key}
你使用严格和警告是非常好的。
如果性能不是的大问题
(sort {$words{$a} <=> $words{$b}} keys %words)[0..4])
如果你绝对需要杀手级的速度,那么在5次迭代后终止的选择排序可能是最适合你的。
my @results;
for (0..4) {
my $maxkey;
my $max = 0;
for my $key (keys %words){
if ($max < $words{$key}){
$maxkey = $key;
$max = $words{$key};
}
}
push @results, $maxkey;
delete $words{$maxkey};
}
say join(","=>@results);
有CPAN模块,Sort::Key::Top。它有一个直接的接口和一个高效的XS实现:
use Sort::Key::Top qw(rnkeytop);
my @results = rnkeytop { $words{$_} } 5 => keys %words;