2
votes

syntaxe pour plusieurs tableaux dans une seule boucle foreach en perl

J'ai besoin de connaître la syntaxe appropriée pour plusieurs tableaux dans une seule boucle foreach.

En TCL, nous pouvons avoir plusieurs listes dans une seule boucle foreach. Mais comment faire avec perl?

#TCL eg:
foreach i $a j $e {

}


0 commentaires

5 Réponses :


1
votes

Pour quelqu'un qui ne connaît pas TCL, ce que vous voulez n'est pas clair, mais je pense que vous voulez ce qui suit:

for my $i (0..$#foos) {
   my $foo = $foos[$i];
   my $bar = $bars[$i];
   ...
}


0 commentaires

2
votes

La syntaxe TCL n'est pas claire, je suis donc allé à la source, c'est-à-dire tclsh:

$ perl dummy.pl
0 '1' '4'
1 '2' '5'
2 '3' '6'
3 '4' '7'
4 '' '0'
5 '' '9'

TCL foreach :

Les valeurs de chaque liste sont utilisées dans l'ordre du premier au dernier, et chaque valeur est utilisée exactement une fois. Le nombre total d'itérations de boucle est suffisamment grand pour utiliser toutes les valeurs de toutes les listes de valeurs. Si une liste de valeurs ne contient pas suffisamment d'éléments pour chacune de ses variables de boucle à chaque itération, des valeurs vides sont utilisées pour les éléments manquants.

En Perl, les éléments "vides" sont undef , donc je suppose que la traduction la plus proche de Perl serait:

#!/usr/bin/perl
use strict;
use warnings;

use List::Util qw(max);

my @a = (1, 2, 3, 4);
my @e = (4, 5, 6, 7, 0, 9);
my $max_index = max($#a, $#e);

foreach my $index (0..$max_index) {
    my $i = $a[$index] // '';
    my $j = $e[$index] // '';

    # your "TCL" loop code goes here...
    print "$index '$i' '$j'\n";
}

exit 0;

Test sortie:

% set a { 1 2 3 4 }
 1 2 3 4
% set e { 4 5 6 7 0 9 }        
 4 5 6 7 8 9
% foreach i $a j $e { puts "'$i' '$j'" }      
'1' '4'
'2' '5'
'3' '6'
'4' '7'
'' '0'
'' '9'


2 commentaires

Existe-t-il un moyen sans utiliser les modules cpam? Ne pouvons-nous pas le faire de manière standard?


Pourquoi auriez-vous besoin du CPAN? $ corelist List :: Util -> List :: Util a été publié pour la première fois avec perl v5.7.3



1
votes

Avec juste le noyau Perl, il y a aussi la possibilité d'utiliser shift , mais notez que cette méthode modifie (vide) les tableaux, alors utilisez-en des copies si cela compte:

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

my @a = 1 .. 4;
my @e = 5 .. 9;

while (@a || @e) {
  my $i = shift @a // '-';
  my $j = shift @e // '-';

  say "$i\t$j";
}


0 commentaires

3
votes

Les versions actuelles du module List :: MoreUtils fournissent un zip_unflatten qui combinera deux (ou plus) tableaux en un seul tableau contenant des références à un tableau du premier élément de chaque liste, puis du second, et ainsi de suite:

#!/usr/bin/env perl    

use strict;
use warnings;
use 5.010;

use List::MoreUtils 'zip_unflatten';

my @a = 1 .. 4;
my @e = 5 .. 9;

my @z = zip_unflatten(@a, @e);

for my $pair (@z) {
  my $i = $pair->[0] // '-';
  my $j = $pair->[1] // '-';

  say "$i\t$j";
}

( L'opérateur // que j'utilise ici est "defined-OR", qui est fondamentalement le même que || , sauf qu'il fonctionne si la variable à sa gauche a un défini valeur plutôt que si elle a une vraie valeur.)


0 commentaires

2
votes

La fonction List :: UtilsBy zip_by peut être utile pour cette tâche. Malheureusement, il n'existe actuellement aucun moyen efficace de déclarer plusieurs variables d'itération dans une boucle foreach, nous utilisons donc arrayrefs.

use strict;
use warnings;
use List::UtilsBy 'zip_by';
my @arr1 = ...;
my @arr2 = ...;
foreach my $zipped (zip_by { [@_] } \@arr1, \@arr2) {
  my ($i, $j) = @$zipped;
  ...
}

Le List :: SomeUtils La fonction zip effectue cette même tâche de manière plus concise, mais a un prototype difficile nécessitant des tableaux, où zip_by code> est plus flexible.


0 commentaires