Perl:在散列数组中找到最大值和最小值

时间:2017-10-02 23:03:31

标签: arrays perl sorting hash

我在Perl中有以下结构:

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

my %hash = (
    'firstitem' => {
        '1' => ["A","99"],
        '2' => ["B","88"],
        '3' => ["C","77"],
    },
    'seconditem' => {
        '3' => ["C","100"],
        '4' => ["D","200"],
        '5' => ["E","300"],
    },
);

我正在寻找一种方法来查找每个哈希数组中的最大数量和最小数量。 所以输出将是

firstitem: max:99, min:77
seconditem: max:300, min:100

我的想法是先对二级密钥进行排序,然后在for循环中进行冒泡排序或其他排序。它看起来不是很优雅和聪明。

    foreach my $k1 (keys %hash) {
        my $second_hash_ref = $hash{$k1};                   
        my @sorted_k2 = sort { $a <=> $b } keys %{$second_hash_ref}; 
        foreach my $i (0..$#sorted_k3){ 
            #bubble sort or other sort
        }
    }

2 个答案:

答案 0 :(得分:5)

List::Util是提供minmax功能的核心模块:

use strict;
use warnings;

use List::Util qw(min max);

my %hash = (
    'firstitem' => {
        '1' => ["A","99"],
        '2' => ["B","88"],
        '3' => ["C","77"],
    },
    'seconditem' => {
        '3' => ["C","100"],
        '4' => ["D","200"],
        '5' => ["E","300"],
    },
);

for my $key (keys(%hash)) {
    my @numbers = map { $_->[1] } values(%{$hash{$key}});
    printf("%s: max: %d, min: %d\n", $key, max(@numbers), min(@numbers));
}

输出:

firstitem: max: 99, min: 77
seconditem: max: 300, min: 100

答案 1 :(得分:2)

你快到了。

一旦你到达第二级,你需要的是数字的整个列表,以便能够找到该批次的最大值和最小值。由于您需要子项中所有数组的极值,因此您不需要迭代二级键。

此外,您可以获取所有数组内容,除非保证数字位于特定位置。然后使用grepScalar::Util::looks_like_number来过滤掉不是数字的元素。

最后,对键进行排序没有任何好处。

use warnings;
use strict;
use feature 'say';

use Scalar::Util 'looks_like_number';
use List::MoreUtils 'minmax';

my %hash = ( 
    'firstitem' => {
        '1' => ["A","99"], '2' => ["B","88"], '3' => ["C","77"],
    },  
    'seconditem' => {
        '3' => ["C","100"], '4' => ["D","200"], '5' => ["E","300"],
    },  
);


foreach my $k1 (keys %hash) 
{
    my @nums = 
        grep { looks_like_number($_) } 
        map  { @{ $hash{$k1}{$_} } }
        keys %{$hash{$k1}};

    my ($min, $max) = minmax @nums;

    say "$k1: max = $max, min = $min";
}

这将打印预期值。如果您的实际哈希值与显示完全相同,则可以values %{$hash{$k1}}直接提取arrayrefs,并使用map { @$_ }取消引用它们。

由于你需要两个极端,因此List::MoreUtilsminmax非常合适,这是&#34; 最有效的算法&#34;为了工作。算法的性能在模块的XS版本中完全实现,而Perl版本有一些开销。

另请注意核心List::Util模块,其中包含个人minmax以及其他实用程序。