perl 按值对多维散列进行排序并打印最高

cvxl0en2  于 2022-11-15  发布在  Perl
关注(0)|答案(3)|浏览(226)

我有一个存储的多维散列(%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

ldioqlga

ldioqlga1#

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";
cld4siwp

cld4siwp2#

有时候最难的事情就是准确地定义问题。

#!/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

ruoxqz4g

ruoxqz4g3#

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

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

相关问题