Poți forța fie un scalar sau ref matrice să fie o matrice în Perl?

voturi
25

Am o variabilă perl $resultscare devine întors de la un serviciu. Valoarea ar trebui să fie o matrice, și $resultsar trebui să fie o referință matrice. Cu toate acestea, în cazul în care matricea are un singur element în ea, $resultsva fi setat la această valoare, și nu o matrice de referință care conține ca un element.

Vreau să fac o foreachbuclă pe matrice așteptat. Fără control ref($results) eq 'ARRAY', există o modalitate de a avea ceva echivalent cu următorul text:

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

Această probă de cod particular va lucra pentru referință, dar se va plânge pentru scalar simplu.

EDIT: Ar trebui să se clarifice faptul că nu există nici o cale pentru mine de a schimba ceea ce este returnat de la serviciu. Problema este că valoarea va fi un scalar, atunci când există doar o singură valoare și va fi o referință matrice atunci când există mai mult de o valoare.

Întrebat 06/08/2008 la 06:56
sursa de către utilizator
În alte limbi...                            


6 răspunsuri

voturi
26

nu im sigur că există nici un alt mod decât:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....
Publicat 06/08/2008 la 08:13
sursa de către utilizator

voturi
12

O altă soluție ar fi să-și încheie apelul la server și să-l întoarcă întotdeauna o matrice pentru a simplifica tot restul vieții tale:

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

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

Apoi, puteți ști întotdeauna că veți primi înapoi o trimitere la o matrice, chiar dacă a fost doar un singur element.

foreach my $item (@{call_to_service()})
{
  ...
}
Publicat 19/08/2008 la 15:16
sursa de către utilizator

voturi
2

Ei bine, dacă nu poți să faci ...

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

sau asta...

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

atunci s-ar putea să încercați ceva înfricoșător păros ca asta! ....

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

și pentru a evita ca șir de caractere periculoase eval devine foarte urat Fugly !! ....

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

PS. Preferința mea ar fi să-l abstractă departe în sub call_to_service exemplul ala () dat de reatmon.

Publicat 12/10/2008 la 22:14
sursa de către utilizator

voturi
0

O poți face așa:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Publicat 23/11/2016 la 05:34
sursa de către utilizator

voturi
0

Aș re-factor codul din interiorul buclei și apoi face

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

Desigur, aș face doar că în cazul în care codul din bucla a fost non-triviale.

Publicat 14/08/2008 la 22:41
sursa de către utilizator

voturi
0

Am testat doar asta cu:

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

Și se pare să funcționeze bine, așa că mă gândesc că are ceva de-a face cu rezultatul obtinerea întors de la serviciu? Dacă nu aveți nici un control asupra serviciului returnarea acest lucru ar putea fi greu unul pentru a sparge

Publicat 06/08/2008 la 07:22
sursa de către utilizator

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