Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, I want 2 arrays to be parsed in parallel and create a new array where the first element of first array & first element of second array are combined and they become the first element of the new array. i.e,

array1 = (one,two,three) array2 = (1,2,3) combinedarray = (one:1,two:2,three:3) i am using perl version perl5.8.8. Thanks in advance.

Replies are listed 'Best First'.
Re: iterating 2 arrays in parallel
by linuxer (Curate) on Apr 15, 2009 at 09:48 UTC
    use List::MoreUtils qw( pairwise ); my @combined = pairwise { $a .':'. $b } @array1, @array2;

    See List::MoreUtils for details.

      pairwise from List::MoreUtils requires that both arrays have the same length, you can get the same behaviour easily without using any extra module at all:

      my @combined = map {"$a1[$_]:$a2[$_]"} ($#a1 < $#a2 ? (0..$#a2) : (0.. +$#a1));

      This version can be easily fixed to treat arrays of different length:

      my @combined = map {($a1[$_]//"").":".($a2[$_]//"")} ($#a1 < $#a2 ? (0 +..$#a2) : (0..$#a1));

      citromatik

        The given example uses arrays of the same length, so pairwise looks fine to me.

        And if they are not of the same length, I think the same way as JavaFan, that iswas left as an exercise to the reader. I don'tdidn't want to guess, what has to happen if the lengths differ. It's the OP who should know, what to do.

        Nevertheless, thanks for your examples ;o)

        Update:

        What about this pairwise solution to work with arrays of different lengths:

        use List::MoreUtils qw( pairwise ); my @a=(1 .. 5 ); my @b=( 'a' .. 'c' ); ### Good point from JavaFan; bad idea to ignore 0 ### my @combined = pairwise { ( $a || '' ) .':'. ( $b || '' ) } @a, @b +; ### fixed: my @combined = pairwise { ( defined $a ? $a : '' ) .':'. ( defined $b +? $b : '' ) } @a, @b; { local $,="\n", print @combined; }
Re: iterating 2 arrays in parallel
by vinoth.ree (Monsignor) on Apr 15, 2009 at 09:56 UTC

    Just try it

    my @array1 = ('one','two','three') ; my @array2 = (1,2,3) ; &combinearray(\@array1,\@array2); sub combinearray{ my @arr1=@{$_[0]}; my @arr2=@{$_[1]}; my @combinarr; foreach my $var(@arr1){ my $tem=$var.':'.shift @arr2; push(@combinarr,$tem); } print "@combinarr"; }
    Vinoth,G
Re: iterating 2 arrays in parallel
by JavaFan (Canon) on Apr 15, 2009 at 09:43 UTC
    There are many ways. One of them:
    my @combinearray; for (my $i = 0; $i < @array1; $i++) { $combinearray[$i] = [$array1[$i], $array2[$i]]; }
    What to do if the arrays are not of equal length is left as an exercise to the reader.
        Ah, the "There's only one (proper) way to do it" attitude.

        Sorry, but you can find Python around the next corner.

Re: iterating 2 arrays in parallel
by ambrus (Abbot) on Apr 15, 2009 at 10:33 UTC
Re: iterating 2 arrays in parallel
by ikegami (Patriarch) on Apr 15, 2009 at 14:14 UTC
    The MapCar family in Algorithm::Loops does this. The different MapCar subs handle arrays of mismatched length differently.
    use Algorithm::Loops qw( MapCar ); my @array1 = qw( one two three ); my @array2 = ( 1, 2, 3 ); my @combined = MapCar { join ':', @_ } \@array1, \@array2;
Re: iterating 2 arrays in parallel
by targetsmart (Curate) on Apr 15, 2009 at 10:01 UTC
    One more way
    perl -MData::Dumper -e '@a=0..9;@b=split(//,"x"x10); @c = map{ $_.":". +shift @a } @b; print Dumper \@c';

    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
Re: iterating 2 arrays in parallel
by pat_mc (Pilgrim) on Apr 15, 2009 at 10:13 UTC
    Or even shorter:
    my @array1=(one, two, three); my @array2=(1, 2, 3); my @combined; map {push @combined,"$_:$array2[$counter++]"} @array1;'

    Cheers - Pat

      map { push ... } is a rather silly construct. Better solutions:

      my $counter = 0; my @combined; push @combined, "$_:$array2[$counter++]" for @array1;
      my $counter = 0; my @combined = map { "$_:$array2[$counter++]" } @array1;

      Having two independent but equivalent iterators is overly complex. Better:

      my @combined = map { "$array1[$_]:$array2[$_]" } 0..$#array1;