如何找到与最大计算值相关的密钥?

时间:2011-11-13 00:28:03

标签: perl hash

我试图找出散列中的最大值以及该最大值的相应键。我的哈希看起来像

%hash = (
    bob => "4.9",
    gita => "3.9 , 6.8",
    diu => "3.0",
);

现在我想用它所属的键找到该哈希中的最大值。

所需的输出是

gita 6.8  

我正在尝试按升序对%hash中的值进行排序,以获得这样的最大值

sub hashValueAscendingNum {
    $hash{$a} cmp $hash{$b};
}

foreach my $highest (sort hashValueAscendingNum(keys(%hash))) {
    print "\t $hash{$highestMagnitude} \t\t $highest \n";
}

我希望检查哈希中的所有值,并且应该使用其键返回具有最大值的值。

我该怎么做?

4 个答案:

答案 0 :(得分:1)

您需要先将每个密钥与原始%hash中与其对应的最高值相关联,然后找到与最高值关联的密钥。

#!/usr/bin/env perl

use strict; use warnings;

use List::Util qw( max );

my  %hash = (
    bob => [ 4.9 ],
    gita => [ 3.9, 6.8 ],
    diu => [ 3.0 ],
);

my %max = map { $_ => max @{ $hash{$_} } } keys %hash;

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

print join(' => ', $argmax, $max), "\n";

当然,这是非常低效的(尤其是使用sort),但对于您展示的尺寸,这并不重要。为了完整起见,这是使用each

的更高效版本
#!/usr/bin/env perl

use strict; use warnings;

use List::Util qw( max );

my  %hash = (
    bob => [ 4.9 ],
    gita => [ 3.9, 6.8 ],
    diu => [ 3.0 ],
);

my ($argmax, $max) = @{ init_argmax_max(\%hash) };

while (my ($k, $v) = each %hash) {
    $v = max @{ $v };
    if ( $v > $max ) {
        $argmax = $k;
        $max = $v;
    }
}

print join(' => ', $argmax, $max), "\n";

sub init_argmax_max {
    my ($hash) = @_;
    my ($argmax, $max) = each %{ $hash };

    keys %{ $hash };

    $max = max @{ $max };

    return [$argmax, $max];
}

答案 1 :(得分:1)

哈希只有一个密钥和一个值,每个密钥必须是唯一的。在你原来的问题中你有这个:

%hash = (
   bob => "4.9",
   gita =>"3.9 , 6,8",
   diu => "3.0",
);

好吧,gita不能有两个值。也不是,你的哈希中有两个键等于gita。因此,您不能使用简单的哈希来存储您的值。

通过使用引用,可以解决这个问题。例如,哈希中的每个元素都可以包含reference to an array。因此,您的数据结构可能如下所示:

%hash = (
    bob =>  [(4.9)],
    gita => [(3.9, 6.8)],
    diu  => [(3.0)],
);

[]标记对数组的引用。

但是,这并不能真正解决您的特定问题,因为您现在必须遍历散列中的每个键,然后是每个键的数组中的每个元素,并对它们进行排序。您可以创建一个排序子例程,但仅仅因为您可以说sort不能使其有效。

也许你需要的是一个数组数组。这将消除gita具有两个值的问题,但使排序更容易一些。想象一下这样的结构:

my @array = (
    [bob  => 4.9],
    [gita => 3.9],
    [gita => 6.8],
    [diu  => 3.0],
);

现在,我们可以根据@array的值对$array[$x]->[1]进行排序!我们所需要的只是数组@array的每个元素都要将$ a-&gt; [1]与$ b-&gt; [1]进行比较。然后,如果我们对它进行反向排序,那么最大的元素将是$array[0]。名称为$array[0]->[0],元素为$array->[0]->[1]

#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say switch);

my @array = (
    [bob  => 4.9],
    [gita => 3.9],
    [gita => 6.8],
    [diu  => 3.0],
);

@array = reverse sort mysort @array;

say "$array[0]->[0] $array[0]->[1]";

sub mysort {
    $a->[1] <=> $b->[1];
}

输出是:

gita 6.8.

您注意到Perldoc's perllol的链接?如果您之前从未使用过Perl参考资料,我建议您阅读。

答案 2 :(得分:0)

#!/usr/bin/perl
use warnings;
use strict;

my %hash = (
    bob  => [ 4.9 ],
    gita => [ 3.9, 6.8 ],
    diu  => [ 3.0 ],
);

my $max_key;
my $max_val=0;

foreach my $key (keys %hash) {
    foreach my $val ( @{$hash{$key}} ) {
        ($max_key, $max_val) = ($key, $val)
            if $val > $max_val;
    }
}

print "$max_key => $max_val\n";

答案 3 :(得分:0)

你有几个很好的答案。现在是一个坏的(假设您在哈希中修复小数分隔符):

my %hash = (bob => "4.9",
            gita =>"3.9 , 6.8",
            diu => "3.0",
            );

my $max = (map{join" ",@$_[0,1]}sort{$b->[1]-$a->[1]}map{[$_,sort{$b-$a}split(/ , /,$hash{$_})]}keys%hash)[0];

print "$max\n";

输出:

gita 6.8

除非你故意试图打高尔夫球和/或混淆它,否则永远不要这样做。