【问题标题】:Sort multidimensional hash by values and print the highest按值对多维散列进行排序并打印最高的
【发布时间】:2020-03-19 15:54:38
【问题描述】:

我有一个存储的多维散列 (%info),其结构如下:

$info{$os}{$id}=$length;

foreach $os (keys %info){   
    foreach $id (keys %{$info{$os}}){
        print "$os $id => " . $info{$os}{$id} ."\n" if (keys %info > 100);
    }
}

有了这个,我可以读取哈希值并只打印出现次数超过 100 次的 $os,但现在我想只打印 $length(即值)最高的 $id。所以我想按值对哈希进行排序,并仅打印具有最高值的$os$id

有什么帮助吗?

【问题讨论】:

    标签: perl sorting hash


    【解决方案1】:

    有时最难做的事情就是准确地定义问题。试试这个代码:

    #!/usr/bin/perl
    use warnings;
    use strict;
    use integer;
    
    my %info = (
        Debian  => { jessie => 80, buster => 90, bullseye => 110 },
        Fedora  => { fedora_a => 70, fedora_b => 105 },
        Arch    => { arch_a => 50, arch_b => 108 },
        Windows => { vista => 40, win10 => 63 },
        OSX     => { apple => 71 },
    );
    
    my @key_pairs_unsorted;
    for my $os (keys %info) {
        for my $id (keys %{$info{$os}}) {
            push @key_pairs_unsorted, {os => $os, id => $id};
        }
    }
    my @key_pairs_sorted =
      sort { $info{$b->{os}}{$b->{id}} <=> $info{$a->{os}}{$a->{id}} }
      @key_pairs_unsorted;
    
    printf "%-7s %-8s %3d\n",
      $_->{os}, $_->{id}, ${info}{$_->{os}}{$_->{id}}
      for @key_pairs_sorted;
    

    理解这段代码应该可以帮助您准确地定义您的问题,然后您应该能够合理迅速地解决问题。

    如需进一步参考,this questionthis one 可能会感兴趣。

    【讨论】:

      【解决方案2】:
      my($maxos,$maxid,$maxlength);
      foreach my $os (sort keys %info) {
        foreach my $id (keys %{ $info{$os} }) {
          ($maxos,$maxid,$maxlength) = ($os,$id,$info{$os}{$id})
            if !defined $maxlength || $info{$os}{$id} > $maxlength;
        }
      }
      
      print "$maxos $maxid => $maxlength\n";
      

      【讨论】:

      • 如果 OP 实际上不需要排序,这是一个很好的答案。 (他说他需要排序,但有理由推测他可能不需要。)
      【解决方案3】:

      可以使用List::Util::reduce获取每个顶级key中值最大的key

      use List::Util qw(reduce);
      
      for my $os (keys %info) { 
          my $id_max_length = reduce { 
              $info{$os}{$a} > $info{$os}{$b} ? $a : $b 
          } keys %{$info{$os}};
      
          say "$os --> $id_max_length --> $info{$os}{$id_max_length}";
      }
      

      获取所有键中的最大值

      my ($max_os, $max_id) = 
          map { $_->[0], $_->[1] }
          reduce { $info{$a->[0]}{$a->[1]} > $info{$b->[0]}{$b->[1]} ? $a : $b }
          map { [$_, max_id_for_os($_)] } 
          keys %info;
      
      say "$max_os -> $max_id -> $info{$max_os}{$max_id}";
      
      sub max_id_for_os {
          my ($os) = @_; 
          reduce { $info{$os}{$a} > $info{$os}{$b} ? $a : $b } keys %{$info{$os}}
      }
      

      或者,也许更简单,在循环中比较顶级键

      my ($max_os, $max_id) = do {  # initialize
          my ($os) = keys %info;
          $os, (keys %{$info{$os}})[0];
      };
      
      for my $os (keys %info) { 
          my $mid = 
              reduce { $info{$os}{$a} > $info{$os}{$b} ? $a : $b } 
              keys %{$info{$os}};
      
          ($max_os, $max_id) = ($os, $mid) 
              if $info{$os}{$mid} > $info{$max_os}{$max_id};
      }
      
      say "Largest: $max_os -> $max_id -> $info{$max_os}{$max_id}";
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-07
        • 2018-07-12
        • 1970-01-01
        • 2011-12-13
        • 2010-11-02
        • 2014-01-08
        • 2022-11-25
        • 2011-07-15
        相关资源
        最近更新 更多