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

In Perl, how can find the smallest value in a list and keeping the index corresponding to that value?

我想区分 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;

我建议您使用散列 %side 来包含这些值。然后$sside$bside变量可以保存最小值和最大值

的身份ij

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

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 来代替对哈希键的排序。结果相同

my ($sside, $bside) = sort { $side{$a} <=> $side{$b} } keys %side;

在数学中,你指的是argmax and argmin。您可以通过多种方式获得它们的功能。

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

或者,给定一个值列表,你可以在列表中找到对应于极值的索引,然后select其中任何一个对应的值得到极值的值。这是在下面的 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
                      ]
        };

你也可以在不使用任何库的情况下做到这一点,一次找到两个极值。 returns 下面的函数是一个散列引用,它包含两个条目,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
                     ]
                   ]
        };