Können Sie entweder ein Skalar oder Array-ref zwingen, ein Array in Perl zu sein?

stimmen
25

Ich habe einen Perl - Variable , $resultsdie von einem Dienst zurückgegeben werden. Der Wert sollte ein Array sein und $resultssoll eine Array - Referenz sein. Wenn jedoch das Array nur ein Element in sich hat, $resultswird auf diesen Wert gesetzt werden, und nicht eine referenzierte Array, das ein Element enthält.

Ich möchte ein tun foreachSchleife auf dem erwarteten Array. Ohne Kontrolle ref($results) eq 'ARRAY', ist es eine Möglichkeit , etwas entspricht dem folgenden haben:

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

Dieses spezielle Codebeispiel wird für die Referenz arbeitet, wird aber für die einfachen skalare beschweren.

EDIT: Ich soll klarstellen, dass es keine Möglichkeit für mich zu ändern, was aus dem Dienst zurückgeführt wird. Das Problem ist, dass der Wert ein Skalar sein wird, wenn nur ein Wert ist, und es wird eine Array-Referenz sein, wenn es mehr als ein Wert ist.

Veröffentlicht am 06/08/2008 um 06:56
quelle vom benutzer
In anderen Sprachen...                            


6 antworten

stimmen
26

im nicht sicher, eine andere Möglichkeit gibt es als:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....
Beantwortet am 06/08/2008 um 08:13
quelle vom benutzer

stimmen
12

Eine andere Lösung wäre, den Aufruf an den Server zu wickeln und haben es immer ein Array zurück, 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 wissen, dass Sie auf ein Array eine Referenz zurückkommen wird, auch wenn es nur ein Element war.

foreach my $item (@{call_to_service()})
{
  ...
}
Beantwortet am 19/08/2008 um 15:16
quelle vom benutzer

stimmen
2

Nun, wenn Sie nicht tun können ...

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

oder dieses...

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

dann könnten Sie etwas haarige beängstigend wie dieses versuchen haben! ....

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

und um diese gefährliche Zeichenfolge zu vermeiden eval es wirklich hässlich fugly wird !! ....

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

PS. Meine Präferenz zu abstrahieren es weg in sub ala call_to_service () Beispiel durch reatmon gegeben wäre.

Beantwortet am 12/10/2008 um 22:14
quelle vom benutzer

stimmen
0

Sie können es tun, wie folgt:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Beantwortet am 23/11/2016 um 05:34
quelle vom benutzer

stimmen
0

Ich würde den Code innerhalb der Schleife erneut Faktor und dann tun

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

Natürlich würde ich nur das tun, wenn der Code in der Schleife war nicht trivial.

Beantwortet am 14/08/2008 um 22:41
quelle vom benutzer

stimmen
0

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, ok zu arbeiten, so dass ich denke, es hat etwas mit dem Ergebnis zu tun, aus dem Dienst zurück zu werden? Wenn Sie keine Kontrolle über die Rückkehr Service haben könnte dies schwierig sein, einen zu knacken

Beantwortet am 06/08/2008 um 07:22
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more