Kun je dwingen ofwel een scalair of matrix ref om een ​​array in Perl?

stemmen
25

Ik heb een perl variabele $resultsdat wordt terug van een service. De waarde wordt verondersteld een array, en $resultsmoet een array referentie. Wanneer de array slechts één punt daarin, $resultswordt ingesteld op die waarde, en niet een referentie array die een bericht bevat.

Ik wil een doen foreachlus op de verwachte array. Zonder controle ref($results) eq 'ARRAY', is er een manier om iets gelijkwaardig is aan het volgende:

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

Dat bepaalde code monster werken voor de referentie, maar zal klagen om de eenvoudige scalaire.

EDIT: Ik moet verduidelijken dat er geen manier voor mij om te veranderen wat is teruggekeerd van de service. Het probleem is dat de waarde een scalair is wanneer er slechts één waarde en is een rasterverwijzing zijn wanneer er meer dan één waarde.

De vraag is gesteld op 06/08/2008 om 06:56
bron van user
In andere talen...                            


6 antwoorden

stemmen
26

im niet zeker dat er een andere manier dan:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....
antwoordde op 06/08/2008 om 08:13
bron van user

stemmen
12

Een andere oplossing zou zijn om de oproep te wikkelen naar de server en het altijd hebben een array terug te keren naar de rest van je leven te vereenvoudigen:

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

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

Dan kunt u altijd weet dat je terug te krijgen een verwijzing naar een array, zelfs al was het maar één punt.

foreach my $item (@{call_to_service()})
{
  ...
}
antwoordde op 19/08/2008 om 15:16
bron van user

stemmen
2

Nou als je niet kunt doen ...

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

of dit...

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

dan moet je zou kunnen hebben om iets harige eng als dit proberen! ....

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

en die gevaarlijk koord vermijden eval wordt het pas echt lelijk fugly !! ....

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

PS. Mijn voorkeur zou abstraheren net in sub ala call_to_service () voorbeeld dat reatmon.

antwoordde op 12/10/2008 om 22:14
bron van user

stemmen
0

Je kunt het als volgt uit:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
antwoordde op 23/11/2016 om 05:34
bron van user

stemmen
0

Ik zou re-factor de code binnen de lus en dan doen

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

Natuurlijk zou ik alleen doen als de code in de loop was niet triviaal.

antwoordde op 14/08/2008 om 22:41
bron van user

stemmen
0

Ik heb dit net getest met:

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

En het lijkt te werken ok, dus ik denk dat het iets te maken heeft met het resultaat krijgen terug van de dienst? Als je hebt geen controle over de terugkerende dienst zou dit moeilijk zijn een te kraken

antwoordde op 06/08/2008 om 07:22
bron van user

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