2016-11-18 5 views
0

Ich suche den Unterschied zwischen side_i und side_j zu unterscheiden, um den kleinsten Wert zu finden ... gefolgt von ... um dann den kleinsten und den größten mit einer gegebenen Zahl zu multiplizieren.In Perl, wie kann man den kleinsten Wert in einer Liste finden und den Index zu diesem Wert halten?

Das ist ziemlich einfach zu tun. Ich möchte jedoch immer noch zwischen i und j unterscheiden können, so dass ich weiß, welches das ist, nachdem sie multipliziert wurden.

Das ist was ich bisher habe. Bitte beachten Sie, ich bin ein sehr neuer Benutzer von Perl und allgemeiner Codierung:

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; 

Antwort

3

Ich schlage vor, dass Sie einen Hash %side die Werte enthalten verwenden. Dann können die $sside und $bside Variablen halten die Identitäten i und j der kleinsten und größten Werte

Sie erklären nicht, was Sie tun wollen, nachdem Sie festgestellt haben, was was ist, so meine Multiplikationen am Ende sind wahrscheinlich Weg von

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; 

Wenn Sie möchten, können Sie sort stattdessen verwenden, um die Hash-Schlüssel zu bestellen. Das Ergebnis ist identisch

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

35 Punkte gehen und es zeigt bereits 100k. Du hast bald eine Tasse auf deinem Weg! :) – simbabque

+0

Ich hatte gehofft, diese Funktion wiederverwenden zu können, daher habe ich es in ein Sub eingefügt. Ich werde zuerst über% hash lesen und zurückkommen. Vielen Dank für Ihren Vorschlag bis jetzt! – AlexAMP

+0

@simbabque: Ist das immer noch eine Sache? – Borodin

1

In Mathe, was Sie sich beziehen, sind argmax und argmin genannt. Sie können ihre Funktionalität auf verschiedene Arten erhalten.

Zuerst, eine Liste von Werten gegeben, können Sie ihr Maximum und Minimum finden, und wählen Sie dann die Indizes, die den Elementen der Liste mit den maximalen bzw. minimalen Werten entsprechen. Dies ist in der folgenden Funktion using_only_max_min implementiert. Beachten Sie, dass diese Methode zwei Übergänge über das Array für jedes Extremum durchführt: Einmal, um das Extremum zu finden, und ein anderes Mal, um die entsprechenden Indizes zu finden.

Oder, bei einer Liste von Werten, können Sie die Indizes finden, die den Extrema in der Liste entsprechen, und dann den entsprechenden Wert für jeden von ihnen auswählen, um den Wert des Extremums zu erhalten. Dies ist in der folgenden using_by_functions Routine implementiert.

#!/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, 
    }; 
} 

Ausgang:

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

Sie können dies auch tun, ohne Bibliotheken und finden die beiden Extrema in einem Rutsch. Die folgende Funktion gibt eine Hash-Referenz zurück, die zwei Einträge enthält: max und min. Jede dieser Stelle auf eine Liste, deren ersten Wert ist der Wert des Extremums, und der zweite Wert ist die Liste von Indizes auf das Extremum entsprechen:

#!/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, 
    }; 
} 

Output:

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