1

我有一个哈希值,按从大到小排序。我将如何获得前 5 名?这里有一篇文章谈到只获得一个值。

从 Perl 中的哈希中获取具有最高值的键的最简单方法是什么?

我明白了,所以可以说让这些值将它们添加到数组中并删除散列中的元素,然后再次执行该过程?

似乎应该有一种更简单的方法来做到这一点。

我的哈希称为 %words。

已编辑取出代码作为问题的答案,而实际上并不需要它。

4

3 回答 3

5

您的问题是如何从哈希中获取五个最高值。你有这个代码:

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}

使用严格和警告非常好。

于 2012-12-04T05:40:42.150 回答
3

如果性能不是什么大问题

(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);
于 2012-12-04T04:22:13.193 回答
1

有一个 CPAN 模块,Sort::Key::Top。它有一个直接的接口和一个高效的 XS 实现:

use Sort::Key::Top qw(rnkeytop);

my @results = rnkeytop { $words{$_} } 5 => keys %words;
于 2012-12-04T12:20:43.283 回答