在 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
变量可以保存最小值和最大值
的身份i
和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
来代替对哈希键的排序。结果相同
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 下面的函数是一个散列引用,它包含两个条目,max
和 min
。每一个都指向一个列表,其第一个值是极值的值,第二个值是对应于极值的索引列表:
#!/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
]
]
};
我想区分 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
变量可以保存最小值和最大值
i
和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
来代替对哈希键的排序。结果相同
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 下面的函数是一个散列引用,它包含两个条目,max
和 min
。每一个都指向一个列表,其第一个值是极值的值,第二个值是对应于极值的索引列表:
#!/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 ] ] };