2016-11-18 3 views
0

私は、side_iとside_jの違いを区別するために、最小の値を見つけようとしていますが、...と続き、最小のものと最大のものに与えられた数を掛けます。Perlでは、リスト内の最小値を見つけてその値に対応するインデックスを保持する方法はありますか?

これはかなり簡単です。しかし、私はまだiとjを区別することができるようにしたいと思います。

これはこれまで私が行ってきたことです。

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; 

答えて

3

私はあなたが値を格納するハッシュ%sideを使用することを示唆している:私はPerlと一般的なコーディングの非常に新しいユーザー午前、注意してください。その後$sside$bside変数は、どのので、最後に私の乗算はおそらくあるかが決定した後あなたが何をしたいのか説明していない最小と最大の値

のアイデンティティijを保持することができますway off

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を使用してハッシュキーを注文することができます。結果は、あなたがargmaxargminと呼ばれているを参照しているものを、

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

35ポイント移動しますすでに100kを表示しています。あなたはすぐにあなたの方法を来ているマグカップを持っている! :) – simbabque

+0

私はこの関数を再利用できることを望んでいたので、なぜそれをサブに入れましたか?私は最初に%hashを読んでこれに戻ってくるつもりです。これまでのご意見ありがとうございます! – AlexAMP

+0

@イムバンク:まだそれは何ですか? – Borodin

1

数学で同じです。さまざまな方法で機能を利用できます。

まず、値のリストがあれば、それらの最大値と最小値を見つけて、最大値と最小値を持つリストの要素にそれぞれ対応するインデックスを選択できます。これは下記のusing_only_max_min関数で実装されています。この方法では、極値ごとに2回、極値を見つけるために1回、対応する指標を見つけるためにもう1回、各極値の2つのパスを作成します。

また、値のリストがあれば、リスト内の極値に対応するインデックスを見つけて、それらのいずれかの極値に対応する値を選択して極値の値を取得することができます。これは、下記の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 
         ] 
     };

あなたはまた、任意のライブラリを使用せずにこれを行うには、一度に2つの極値を見つけることができます。以下の関数は、maxminの2つのエントリを含むハッシュリファレンスを返します。その最初の値の極値の値であり、第2の値が極値に対応するインデックスのリストであり、リストにそれらの点の各々:

#!/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 
        ] 
        ] 
     };
関連する問題