在Perl中获取具有最高值的密钥的最简单方法是什么?

时间:2010-05-22 03:50:21

标签: perl hash max

从Perl中获取具有最高值的密钥的最简单方法是什么?

8 个答案:

答案 0 :(得分:34)

使用sort的解决方案:

(sort {$hash{$a} <=> $hash{$b}} keys %hash)[0]

在其他一些答案中发现它非常优雅,但它的表现并不像它看起来那么好。首先,排序会将O(n)搜索搜索操作转换为O(n log n)搜索操作。其次,排序解决方案具有n log n哈希查找。哈希查找对于某些操作非常有用,但在使用整个哈希时,查找比使用eachkeysvalues来迭代数据要慢结构体。这是因为迭代器不需要计算键的哈希值,也不需要反复遍历块来查找值。并且开销不是恒定的,而是随着哈希变大而增加。

以下是一些更快的解决方案:

use strict;
use warnings;

my %hash = (
    small   => 1,
    medium  => 5,
    largest => 10,
    large   => 8,
    tiny    => 0.1,
);

以下是使用each迭代器(O(1)操作完成n次)的解决方案:

sub largest_value (\%) {
    my $hash = shift;
    keys %$hash;       # reset the each iterator

    my ($large_key, $large_val) = each %$hash;

    while (my ($key, $val) = each %$hash) {
        if ($val > $large_val) {
            $large_val = $val;
            $large_key = $key;
        }
    }
    $large_key
}

print largest_value %hash; # prints 'largest'

或者更快的版本,用于交换内存以获得速度(它会生成哈希的副本):

sub largest_value_mem (\%) {
    my $hash   = shift;
    my ($key, @keys) = keys   %$hash;
    my ($big, @vals) = values %$hash;

    for (0 .. $#keys) {
        if ($vals[$_] > $big) {
            $big = $vals[$_];
            $key = $keys[$_];
        }
    }
    $key
}

print largest_value_mem %hash; # prints 'largest'

以下是各种散列大小的性能:

10 keys:              Rate largest_with_sort largest_value largest_value_mem
largest_with_sort 111565/s                --           -8%              -13%
largest_value     121743/s                9%            --               -5%
largest_value_mem 127783/s               15%            5%                --

50 keys:             Rate  largest_with_sort largest_value largest_value_mem
largest_with_sort 24912/s                 --          -37%              -40%
largest_value     39361/s                58%            --               -6%
largest_value_mem 41810/s                68%            6%                --

100 keys:            Rate  largest_with_sort largest_value largest_value_mem
largest_with_sort  9894/s                 --          -50%              -56%
largest_value     19680/s                99%            --              -12%
largest_value_mem 22371/s               126%           14%                --

1,000 keys:         Rate   largest_with_sort largest_value largest_value_mem
largest_with_sort  668/s                  --          -69%              -71%
largest_value     2183/s                227%            --               -7%
largest_value_mem 2341/s                250%            7%                --

10,000 keys:        Rate   largest_with_sort largest_value largest_value_mem
largest_with_sort 46.5/s                  --          -79%              -81%
largest_value      216/s                365%            --              -11%
largest_value_mem  242/s                421%           12%                --

正如您所看到的,如果内存不是问题,那么内部数组的版本是最快的,紧随其后的是each迭代器,并且距离很远...... sort

答案 1 :(得分:9)

不确定为什么每个人都这样做......

use List::Util qw( reduce );
my $max_val_key = reduce { $hash{$a} > $hash{$b} ? $a : $b } keys %hash;

答案 2 :(得分:6)

与散列排序的其他答案相比,以下更节省空间并且将以O(n)而不是O(n log n)运行。它假设值是大于0的整数,并且散列不是空的,但应该很容易扩展为你的情况。

my $key_for_max_value;
my $max_value = -1;
while ((my $key, my $value) = each %hash) {
  if ($value > $max_value) {
    $max_value = $value;
    $max_key = $key;
  }
}

$ key_for_max_value现在将是与最高值对应的键。

答案 3 :(得分:4)

按值排序的键,从最低到最高:

sort { $hash{$a} <=> $hash{$b} } keys %hash

按值排序的键,从最高到最低:

reverse sort { $hash{$a} <=> $hash{$b} } keys %hash

第一个元素

(reverse sort { $hash{$a} <=> $hash{$b} } keys %hash)[0]

cmp替换宇宙飞船来品尝。

答案 4 :(得分:3)

my ($max_key, $max_val) = each %hash or die "hash is empty";
while (my ($key, $val) = each %hash) {
  $max_key = $key, $max_val = $val if $val > $max_val;
}

答案 5 :(得分:1)

my $highest_val = (keys {$hash{$b} <=> $hash{$a}} keys %hash)[0];

答案 6 :(得分:1)

my $highest_val = (sort { $hash{$a} <=> $hash{$b} } keys %hash)[0];

可能就是你想要的。

如果你有一个非常大的哈希,你可能想要使用类似Schwartzian变换的东西:

my @array = map {[$hash{$_},$_]} keys %hash;
my $key_with_highest_value = (sort { $a->[0] <=> $b->[0] } @array)[0]->[1]

答案 7 :(得分:0)

如果性能不是问题,我建议更多literate programming解决方案。

use List::Util qw(max);
max keys %hash;