Frage

Ich habe eine Perl-Variable $results das von einem Dienst zurückgegeben wird.Der Wert soll ein Array sein und $results sollte eine Array-Referenz sein.Wenn das Array jedoch nur ein Element enthält, $results wird auf diesen Wert gesetzt und nicht auf ein referenziertes Array, das dieses eine Element enthält.

Ich möchte ein machen foreach Schleife auf dem erwarteten Array.Ohne zu prüfen ref($results) eq 'ARRAY', gibt es eine Möglichkeit, etwas zu haben, das dem Folgenden entspricht:

foreach my $result (@$results) {
    # Process $result
}

Dieses spezielle Codebeispiel funktioniert für die Referenz, beschwert sich jedoch für den einfachen Skalar.

BEARBEITEN:Ich sollte klarstellen, dass es für mich keine Möglichkeit gibt, zu ändern, was vom Dienst zurückgegeben wird.Das Problem besteht darin, dass der Wert ein Skalar ist, wenn nur ein Wert vorhanden ist, und eine Array-Referenz, wenn mehr als ein Wert vorhanden ist.

War es hilfreich?

Lösung

Ich bin mir nicht sicher, ob es einen anderen Weg gibt als:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....

Andere Tipps

Eine andere Lösung wäre, den Aufruf an den Server zu packen und ihn immer ein Array zurückgeben zu lassen, um den Rest Ihres Lebens zu vereinfachen:

sub call_to_service
{
    my $returnValue = service::call();

    if (ref($returnValue) eq "ARRAY")
    {
        return($returnValue);
    }
    else
    {
       return( [$returnValue] );
    }
}

Dann können Sie immer sicher sein, dass Sie einen Verweis auf ein Array zurückerhalten, auch wenn es nur ein Element war.

foreach my $item (@{call_to_service()})
{
  ...
}

Na ja, wenn du es nicht kannst...

for my $result ( ref $results eq 'ARRAY' ? @$results : $results ) {
    # Process result
}

oder dieses...

for my $result ( ! ref $results ? $results : @$results ) {
    # Process result
}

Dann müssen Sie vielleicht so etwas Haariges und Gruseliges ausprobieren!...

for my $result ( eval { @$results }, eval $results ) {
    # Process result
}

und um diese gefährliche String-Bewertung zu vermeiden, wird es wirklich hässlich!!

for my $result ( eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] } ) {
    # Process result
}

PS.Ich bevorzuge es, es in einem Beispiel von call_to_service() von reatmon zu abstrahieren.

Ich würde den Code innerhalb der Schleife umgestalten und es dann tun

if( ref $results eq 'ARRAY' ){
    my_sub($result) for my $result (@$results);
}else{
    my_sub($results);
}

Das würde ich natürlich nur tun, wenn der Code in der Schleife nicht trivial wäre.

Ich habe das gerade getestet mit:

#!/usr/bin/perl -w
use strict;

sub testit {

 my @ret = ();
 if (shift){
   push @ret,1;
   push @ret,2;
   push @ret,3;
}else{
  push @ret,"oneonly";
}

return \@ret;
}

foreach my $r (@{testit(1)}){
  print $r." test1\n";
}
foreach my $r (@{testit()}){
   print $r." test2\n";
}

Und es scheint gut zu funktionieren, also denke ich, dass es etwas mit dem Ergebnis zu tun hat, das vom Dienst zurückgegeben wird?Wenn Sie keine Kontrolle über den zurückkehrenden Dienst haben, ist dies möglicherweise schwer zu knacken

Sie können es so machen:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top