在Perl中,如何找到列表中的最小值并保持索引对应于该值?

时间:2016-11-18 14:34:50

标签: perl max min

我希望区分side_i和side_j之间的区别,以找到最小的值......继续......然后将最小值和最大值乘以给定的数字。

这很简单。但是,我仍然希望能够以这样的方式区分i和j,以便我知道哪一个是在它们成倍增加之后。

这是我到目前为止所拥有的。请注意,我是Perl和一般编码的新用户:

use strict; 
use Getopt::Long;
use List::Util qw(max);
use File::Find;
use warnings 'all';



my $side_i = 24.56; 
my $side_j = 3.56; 
my $maxi = 10;
my $maxj = 10; 
my $threshold = 0.05; 
my $small_side;



(my $sside, my $bside) = smallestTest($side_i, $side_j);


sub smallestTest{

    my $sside;
    my $bside;
    print "$_[0] $_[1] /n";
    if ($_[0]<$_[1]){
        $sside = $_[0];
        $bside = $_[1];
    } else {
        $sside = $_[1];
        $bside = $_[0];
    }
return($sside, $bside);
}
print "Biggest side is $bside /n";

my $newSide_i = $.....*20;
my $newSide_j = $.....*21;

2 个答案:

答案 0 :(得分:4)

我建议您使用哈希global.asax来包含值。然后%side$sside变量可以包含最小和最大值的$bsidei

在确定哪个是哪个之后,你没有解释你想要做什么,所以我最后的乘法很可能没有了

j

如果您愿意,可以使用use strict; use warnings 'all'; my %side = ( i => 24.56, j => 3.56 ); my ($sside, $bside) = $side{i} < $side{j} ? qw/ i j / : qw/ j i /; $side{$sside} *= 20; $side{$bside} *= 21; 来订购哈希键。结果是相同的

sort

答案 1 :(得分:1)

在数学中,您所指的是argmaxargmin。您可以通过各种方式获得其功能。

首先,给定一个值列表,您可以找到它们的最大值和最小值,然后分别选择与列表元素对应的索引,其中包含最大值和最小值。这是在下面的using_only_max_min函数中实现的。请注意,此方法为每个极值在数组上进行两次传递:一次查找极值,另一次查找相应的索引。

或者,给定一个值列表,您可以找到与列表中的极值对应的索引,然后为其中任何一个选择相应的值以获取极值的值。这是在下面的using_by_functions例程中实现的。

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;
use List::AllUtils qw(max min max_by min_by);

my @n = (1, 3, 5, 8, 8, 3, 2, 4, 4, 6);

print Dumper using_only_max_min(\@n);
print Dumper using_by_functions(\@n);

sub using_only_max_min {
    my $n = shift;

    my $max = max @$n;
    my @argmax = grep $n->[$_] == $max, 0 .. $#$n;

    my $min = min @$n;
    my @argmin = grep $n->[$_] == $min, 0 .. $#$n;

    return {
        max => $max,
        argmax => \@argmax,
        min => $min,
        argmin => \@argmin,
    };
}

sub using_by_functions {
    my $n = shift;

    my @argmax = max_by { $n->[$_] } 0 .. $#$n;
    my $max = $n->[$argmax[0]];

    my @argmin = min_by { $n->[$_] } 0 .. $#$n;
    my $min = $n->[$argmin[0]];

    return {
        max => $max,
        argmax => \@argmax,
        min => $min,
        argmin => \@argmin,
    };
}

输出:

$VAR1 = {
          'argmin' => [
                        0
                      ],
          'max' => 8,
          'min' => 1,
          'argmax' => [
                        3,
                        4
                      ]
        };
$VAR1 = {
          'argmax' => [
                        3,
                        4
                      ],
          'min' => 1,
          'max' => 8,
          'argmin' => [
                        0
                      ]
        };

您也可以在不使用任何库的情况下执行此操作,并一次性找到两个极值。下面的函数返回一个哈希引用,其中包含两个条目maxmin。每个都指向一个列表,其第一个值是极值的值,第二个值是与极值对应的索引列表:

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;

my @n = (1, 3, 5, 8, 8, 3, 2, 4, 4, 6);

print Dumper find_extrema(\@n, sub { $_[0] <=> $_[1]});

sub find_extrema {
    my ($n, $cmp) = @_;

    my ($max, $min) = ([$n->[0], [0]], [$n->[0], [0]]);

    for my $i (1 .. $#$n) {
        my $v = $n->[$i];

        my $r = $cmp->($v, $max->[0]);
        if ($r >= 0) {
            $r ? $max = [$v, [$i]] : push @{ $max->[-1] }, $i;
            next;
        }

        my $s = $cmp->($v, $min->[0]);
        if ($s <= 0) {
            $s ? $min = [$v, [$i]] : push @{ $min->[-1] }, $i;
        }
    }

    return {
        max => $max,
        min => $min,
    };
}

输出:

$VAR1 = {
          'min' => [
                     1,
                     [
                       0
                     ]
                   ],
          'max' => [
                     8,
                     [
                       3,
                       4
                     ]
                   ]
        };