我有一个哈希值,按从大到小排序。我将如何获得前 5 名?这里有一篇文章谈到只获得一个值。
从 Perl 中的哈希中获取具有最高值的键的最简单方法是什么?
我明白了,所以可以说让这些值将它们添加到数组中并删除散列中的元素,然后再次执行该过程?
似乎应该有一种更简单的方法来做到这一点。
我的哈希称为 %words。
已编辑取出代码作为问题的答案,而实际上并不需要它。
我有一个哈希值,按从大到小排序。我将如何获得前 5 名?这里有一篇文章谈到只获得一个值。
从 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 $file0\n";
最好$!
在 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/\b\Q$w\E\B//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;