Pouvez-vous forcer soit un scalaire ou ref tableau pour être un tableau en Perl?

voix
25

J'ai une variable perl $resultsqui est renvoyée d'un service. La valeur est censée être un tableau, et $resultsdoit être une référence de tableau. Cependant, lorsque le tableau ne comporte qu'un seul élément en elle, $resultssera fixé à cette valeur, et non un tableau référencé qui contient un élément que.

Je veux faire une foreachboucle sur le tableau prévu. Sans contrôle ref($results) eq 'ARRAY', il est possible d'avoir quelque chose d' équivalent à ce qui suit:

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

Cet échantillon de code particulier fonctionnera pour la référence, mais se plaindra pour le simple scalaire.

EDIT: Je dois préciser qu'il n'y a aucun moyen pour moi de changer ce qui est renvoyé du service. Le problème est que la valeur sera un scalaire quand il n'y a qu'une seule valeur et ce sera une référence de tableau quand il y a plus d'une valeur.

Créé 06/08/2008 à 06:56
source utilisateur
Dans d'autres langues...                            


6 réponses

voix
26

je ne suis pas sûr qu'il ya une autre façon que:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....
Créé 06/08/2008 à 08:13
source utilisateur

voix
12

Une autre solution serait d'envelopper l'appel au serveur et ont toujours retourner un tableau pour simplifier le reste de votre vie:

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

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

Ensuite, vous pouvez toujours savoir que vous récupérerez une référence à un tableau, même si elle était un seul élément.

foreach my $item (@{call_to_service()})
{
  ...
}
Créé 19/08/2008 à 15:16
source utilisateur

voix
2

Eh bien, si vous ne pouvez pas faire ...

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

ou ca...

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

alors vous pourriez avoir à essayer quelque chose poilue effrayant comme ça! ....

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

et pour éviter cette chaîne dangereuse eval il devient vraiment laid fugly !! ....

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

PS. Ma préférence serait abstraite loin dans la sous ala exemple call_to_service () donnée par reatmon.

Créé 12/10/2008 à 22:14
source utilisateur

voix
0

Vous pouvez le faire comme ceci:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Créé 23/11/2016 à 05:34
source utilisateur

voix
0

Je re-facteur le code dans la boucle et faire

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

De Je ne fais évidemment que si le code dans la boucle était non négligeable.

Créé 14/08/2008 à 22:41
source utilisateur

voix
0

Je viens de tester cela avec:

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

Et cela semble fonctionner ok, donc je pense qu'il a quelque chose à voir avec le résultat se revint du service? Si vous avez aucun contrôle sur le service de retour ce pourrait être difficile à une fissure

Créé 06/08/2008 à 07:22
source utilisateur

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