开发者

for with multiple arrays

In Scheme you can iterate over multiple lists in with for-each:

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

I know that in Perl you can use for to iterate over a single list. What's a good way to ite开发者_StackOverflow中文版rate over multiple lists as in the Scheme example?

I'm interested in answers for Perl 5 or 6.


In Perl 6, the Zip operator is the nicest choice. If you want to get both values (and not compute the sum directly), you can use it without the plus sign:

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


In Perl 5 you can use the module List::MoreUtils. Either with pairwise or with the iterator returned by each_array (which can take more than two arrays to iterate through in parallel).

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]";
}


With the Zip operator you can achieve what you're doing with Scheme:

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

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


You could just iterate over the indices of the arrays, if you're sure they're the same size:

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


Algorithm::Loops offers a MapCar function for iterating over multiple arrays (with variants that deal differently with unequally sized arrays).


One way is:

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])

Using each_arrayref from 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])

Thanks to Alex for pointing out List::MoreUtils.


As long as the question is as simple as just adding (/multiplying, dividing,…) and the Arrays are no Arrays of Arrays, you also could use the hyper-operators for your task:

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

(of course this is a Perl6 answer)

if you don't have access to the French quotes «», you could rewrite it as

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


One solution (there are many to choose from) might look like this:

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);

I sense that you are asking about foreach, which might look like this:

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

But it is not as smooth in this case. What happens if either array is shorter?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜