【问题标题】:How do I find the key associated with the maximum computed value?如何找到与最大计算值关联的键?
【发布时间】:2012-12-06 21:51:09
【问题描述】:

我正在尝试找出哈希中的最大值以及该最大值的对应键。我的哈希看起来像

%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";
}

我希望检查散列中的所有值,并应返回具有最大值的值及其键。

我该怎么做?

【问题讨论】:

  • 你至少应该假装努力提出你的问题。这不是%hash,其中有多个值与一个键关联。
  • @SinanÜnür 我不会对 Sonam 太苛刻。他们可能不太了解 Perl,无法理解它并不是真正的哈希。

标签: perl hash


【解决方案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];
}

【讨论】:

    【解决方案2】:

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

    %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[$x]-&gt;[1] 的值对@array 进行排序!对于数组@array 的每个元素,我们只需要比较$a->[1] 和$b->[1]。然后,如果我们对其进行反向排序,最大的元素将是$array[0]。名称为$array[0]-&gt;[0],元素为$array-&gt;[0]-&gt;[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 引用,我建议您阅读它。

    【讨论】:

      【解决方案3】:
      #!/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";
      

      【讨论】:

        【解决方案4】:

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

        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
        

        除非您故意尝试打高尔夫球和/或混淆它,否则切勿这样做。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-20
          • 2016-01-28
          • 2020-10-12
          • 1970-01-01
          • 2010-09-16
          • 2014-06-26
          相关资源
          最近更新 更多