Kan du tvinge enten en skalar eller matrise dommeren å være en matrise i Perl?

stemmer
26

Jeg har en perl variabel $resultssom blir returnert fra en tjeneste. Verdien er ment å være en matrise, og $resultsbør være en matrise referanse. Men når matrisen har bare ett element i den, $resultsvil bli satt til denne verdien, og ikke en referert matrise som inneholder som ett element.

Jeg ønsker å gjøre en foreachløkke på den forventede array. Uten kontroll ref($results) eq 'ARRAY', er det noen måte å ha noe tilsvarende til følgende:

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

Den aktuelle kodeeksempel vil arbeide for referanse, men vil ikke klage for enkel skalar.

EDIT: Jeg må presisere at det ikke er mulig for meg å endre det som er kommet tilbake fra tjenesten. Problemet er at verdien vil være en skalar når det bare er én verdi, og det vil være en matrise referanse når det er mer enn én verdi.

Publisert på 06/08/2008 klokken 05:56
kilden bruker
På andre språk...                            


6 svar

stemmer
26

im ikke sikker på at det finnes noen annen måte enn:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....
Svarte 06/08/2008 kl. 07:13
kilden bruker

stemmer
12

En annen løsning ville være å bryte samtalen til serveren, og har det alltid returnere en matrise for å forenkle resten av ditt liv:

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

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

Deretter kan du alltid vet at du vil få tilbake en referanse til en matrise, selv om det var bare ett element.

foreach my $item (@{call_to_service()})
{
  ...
}
Svarte 19/08/2008 kl. 14:16
kilden bruker

stemmer
2

Vel, hvis du ikke kan gjøre ...

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

eller dette...

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

så du må kanskje prøve noe hårete skummelt som dette! ....

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

og for å unngå at farlige streng eval blir det virkelig stygg fugly !! ....

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

PS. Jeg foretrekker ville være å abstrahere den bort i sub ala call_to_service () eksempel som er gitt ved reatmon.

Svarte 12/10/2008 kl. 21:14
kilden bruker

stemmer
0

Du kan gjøre det slik:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Svarte 23/11/2016 kl. 05:34
kilden bruker

stemmer
0

Jeg ville re-faktor koden innenfor sløyfen og deretter gjøre

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

Selvfølgelig ville jeg bare gjøre det hvis koden i loopen var ikke-triviell.

Svarte 14/08/2008 kl. 21:41
kilden bruker

stemmer
0

Jeg har nettopp testet dette med:

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

Og det ser ut til å fungere ok, så jeg tenker det har noe å gjøre med resultatet bli returnert fra tjenesten? Hvis du har ingen kontroll over retur tjenesten kan dette være vanskelig en å knekke

Svarte 06/08/2008 kl. 06:22
kilden bruker

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