Domanda

Ho una variabile Perl $results che viene restituito da un servizio.Il valore dovrebbe essere un array e $results dovrebbe essere un riferimento all'array.Tuttavia, quando l'array contiene un solo elemento, $results sarà impostato su quel valore e non su un array di riferimento che contiene quell'elemento.

Voglio fare un foreach loop sull'array previsto.Senza controllare ref($results) eq 'ARRAY', c'è un modo per avere qualcosa di equivalente al seguente:

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

Quel particolare esempio di codice funzionerà per il riferimento, ma si lamenterà per il semplice scalare.

MODIFICARE:Vorrei chiarire che non c'è modo per me di modificare ciò che viene restituito dal servizio.Il problema è che il valore sarà scalare quando è presente un solo valore e sarà un riferimento a un array quando è presente più di un valore.

È stato utile?

Soluzione

non sono sicuro che ci sia altro modo oltre a:

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

Altri suggerimenti

Un'altra soluzione sarebbe quella di avvolgere la chiamata al server e fare in modo che restituisca sempre un array per semplificare il resto della tua vita:

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

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

Quindi puoi sempre sapere che otterrai un riferimento a un array, anche se era solo un elemento.

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

Beh, se non puoi farlo...

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

o questo...

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

allora potresti dover provare qualcosa di peloso e spaventoso come questo!...

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

e per evitare quella pericolosa valutazione delle stringhe diventa davvero brutto!!....

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

PS.La mia preferenza sarebbe quella di astrarlo nell'esempio sub ala call_to_service() fornito da reatmon.

Vorrei rifattorizzare il codice all'interno del ciclo e poi farlo

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

Ovviamente lo farei solo se il codice nel ciclo non fosse banale.

L'ho appena testato con:

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

E sembra funzionare bene, quindi penso che abbia qualcosa a che fare con il risultato restituito dal servizio?Se non hai il controllo sul servizio di restituzione, potrebbe essere difficile da decifrare

Puoi farlo in questo modo:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top