2011-06-10 16 views
8

En el esquema se puede iterar sobre varias listas con for-each:para con múltiples matrices

> (for-each (lambda (a b) (display (+ a b)) (newline)) '(10 20 30) '(1 2 3)) 
11 
22 
33 
> 

sé que en Perl puede utilizar for para iterar sobre una lista única. ¿Cuál es una buena forma de iterar en varias listas como en el ejemplo del esquema?

Estoy interesado en respuestas para Perl 5 o 6.

Respuesta

9

En Perl 5 se puede utilizar el módulo de List::MoreUtils. Ya sea con pairwise o con el iterador devuelto por each_array (que puede tomar más de dos arrays para iterar en paralelo).

use 5.12.0; 
use List::MoreUtils qw(pairwise each_array); 

my @one = qw(a b c d e); 
my @two = qw(q w e r t); 

my @three = pairwise {"$a:$b"} @one, @two; 

say join(" ", @three); 

my $it = each_array(@one, @two); 
while (my @elems = $it->()) { 
    say "$elems[0] and $elems[1]"; 
} 
1

Una forma es:

sub for_each 
{ 
    my $proc = shift ; 

    my $len = @{$_[0]} ; 

    for (my $i = 0 ; $i < $len ; $i++) 
    { 
     my @args = map $_->[$i] , @_ ; 

     &$proc (@args) ; 
    } 
} 

for_each sub { say $_[0] + $_[1] } , ([10,20,30],[1,2,3]) 

Usando each_arrayref de List::MoreUtils:

sub for_each 
{ 
    my $proc = shift ; 

    my $it = each_arrayref (@_) ; 

    while (my @elts = $it->()) { &$proc (@elts) } ; 
} 

for_each sub { say $_[0] + $_[1] } , ([10,20,30],[1,2,3]) 

Gracias a Alex para señalar List::MoreUtils .

6

Con el operador postal se puede lograr lo que está haciendo con el esquema:

> .say for (10, 20, 30) Z+ (1, 2, 3) 
11 
22 
33 

Ver http://perlcabal.org/syn/S03.html#Zip_operators

+0

Gracias tadzik. El esquema para cada uno se generaliza a 1 o más listas. ¿Se puede usar zip para más de dos listas? – dharmatech

+2

Puede, aunque Rakudo actualmente solo lo implementa para dos listas (limitación conocida). – moritz

+1

Ahora funciona para cualquier cantidad de listas. – raiph

2

Se podía iterar sobre los índices de los arrays, si está seguro de que son del mismo tamaño:

foreach(0 .. $#array1) { 
    print $array1[$_] + $array2[$_], "\n"; 
} 
2

Algorithm::Loops ofrece una función mapcar para iterar a través de múltiples matrices (con variantes que trata de manera diferente con arreglos de tamaños desiguales).

10

En Perl 6, el operador de Zip es la mejor opción. Si desea obtener ambos valores (y no calcular la suma directa), que se puede utilizar sin el signo más:

for (10, 11, 12) Z (1, 2, 3) -> $a, $b { 
    say "$a and $b"; 
} 
+0

Gracias mortiz! Ver mi comentario a la respuesta de tadzik. – dharmatech

0

Una solución (hay muchos para elegir) podría tener este aspecto:

my @argle = (10, 20, 30); 
my @bargle = (1, 2, 3); 
do { 
    my $yin = shift @argle; 
    my $yang = shift @bargle; 
    say $yin + $yang; 
} while (@argle && @bargle); 

tengo la sensación de que usted está planteando foreach, lo que podría tener este aspecto:

my @argle = (10, 20, 30); 
my @bargle = (1, 2, 3); 
for my $yin (@argle) { 
    my $yang = shift @bargle; 
    say $yin + $yang; 
} 

Pero no es tan fácil en este caso. ¿Qué pasa si cualquiera de las matrices es más corta?

1

Mientras que la pregunta es tan simple como añadir (/ multiplicar, dividir, ...) y los matrices hay órdenes de órdenes, también se podría utilizar los hiper-operadores para su tarea:

<1 2 3> «+» <10 20 30> 

(por supuesto, esto es una respuesta Perl6)

si usted no tiene acceso a las cotizaciones francesas «», podría volver a escribir como

<1 2 3> <<+>> <10 20 30> 
Cuestiones relacionadas