http://qs321.pair.com?node_id=308328

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

Dear monks, I have two arrays, each containing the same number of elements. I want to create a new array whose elements are concatenated elements from the first two arrays, in which the first element from array1 is concatenated with the last element in array2 etc.

I hope this makes sense but here's an example to demonstrate.

my @array1 = ('lots', 'of', 'nice', 'words'); my @array2 = ('red','clothes', 'are', 'fun'); # therefore my new array looks like this; lotsfun ofare niceclothes wordsred
I hope someone can help - my arrays are pretty huge so i guess a loop is needed. Cheers!

Replies are listed 'Best First'.
Re: appending arrays
by broquaint (Abbot) on Nov 19, 2003 at 16:38 UTC
    my @array1 = ('lots', 'of', 'nice', 'words'); my @array2 = ('red','clothes', 'are', 'fun'); my($i, $lastidx) = (0, $#array1); my @concat_array; push @concat_array, $array1[$i] . $array2[$lastidx - $i++] while $i <= $lastidx; print "concatenated array: @concat_array"; __output__ concatenated array: lotsfun ofare niceclothes wordsred
    This will be large array friendly.
    HTH

    _________
    broquaint

Re: appending arrays
by Roy Johnson (Monsignor) on Nov 19, 2003 at 16:36 UTC
    my @new = map($array1[$_] . $array2[-1-$_], 0..$#array1);
    or
    my @new; push (@new, $array1[$_].$array2[-1-$_]) for 0..$#array1;
Re: appending arrays
by Abigail-II (Bishop) on Nov 19, 2003 at 16:52 UTC
    Homework? What have you tried yourself?

    #!/usr/bin/perl use strict; use warnings; sub zip (\@\@) { map {"${$_[0]}[$_]${$_[1]}[$#{$_[0]}-$_]"} 0 .. $#{$_ [0]} } my @array1 = qw /lots of nice words/; my @array2 = qw /red clothes are fun/; my @array3 = zip @array1, @array2; print "@array3\n"; __END__ lotsfun ofare niceclothes wordsred

    Abigail

      See rotate for some ways of getting rid of those unsightly \w characters in zip.

      (Update: meant \d, not \w, not much you can do about _ without ''=~ tricks)

Re: appending arrays
by Bagarre (Sexton) on Nov 19, 2003 at 17:11 UTC

    This works but isn't pretty.

    Any of the GreatOnes want to show us a more elegant solution?

    foreach $item (@array1) { push @array3, $item .pop(@array2); }

    Entities should not be multiplied unnecessarily.
      That will destroy @array2.

      Abigail

      Any of the GreatOnes want to show us a more elegant solution?

      I'm not a GreatOne, but here's how I might have done it assuming that I know the arrays are exactly the same size:

      my $n = $#array1; my @array3 = map { $array1[$_] . $array2[$n-$_] } 0..$n;
      This works but isn't pretty.

      I beg to differ. Your code is very clean, very easy to understand compared to the "line noise" from Abigal.

      -------------------------------------
      Nothing is too wonderful to be true
      -- Michael Faraday

      Eating through the existing arrays:
      push @new, shift(@array1) . pop @array2 while @array1;

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

      That will get the data off the end of @array2, not the beginning. Use shift instead of pop.

      Update: Nothing to see here. Move along. (Must read more carefully next time).

      ----
      I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
      -- Schemer

      : () { :|:& };:

      Note: All code is untested, unless otherwise stated

        That will get the data off the end of @array2, not the beginning.

        Err... Isn't that what the OP wanted? It works fine for me with the OP's data. OK, it destroys @array2, as Abigail-II pointed out. Just for fun, here's a solution that destroys both of the original arrays:

        die "Arrays of different lengths" unless @array1 == @array2; my @array3 = map { shift ( @array1 ) . pop ( @array2 ) } @array1;

        dave

Re: appending arrays
by Art_XIV (Hermit) on Nov 19, 2003 at 18:20 UTC

    The nth way of doing it:

    my @array1 = ('lots', 'of', 'nice', 'words'); my @array2 = ('red','clothes', 'are', 'fun'); my @array3; if (scalar @array1 == scalar @array2) { $array3[$_] = $array1[$_] . $array2[-($_ + 1)] for (0 .. $#array1); } print "@array3\n";
    Hanlon's Razor - "Never attribute to malice that which can be adequately explained by stupidity"
Re: appending arrays
by bivouac (Beadle) on Nov 19, 2003 at 22:06 UTC

    edited again: thanks for the correction. very primative and probably watseful, but it meets the reqs of the spec.

    #!/usr/bin/perl -w use strict; my @one = qw(lots of nice words); my @two = qw(red clothes are fun); my @two_r = reverse @two; my @three; if (scalar @one == scalar @two_r) { for (my $i=0; $i < scalar @one; $i++) { push @three, $one[$i].$two_r[$i]; } } print $three[0], "\n"; print $three[1], "\n"; print $three[2], "\n"; print $three[3], "\n";

    no points for second place in this dojo.

Re: appending arrays
by davido (Cardinal) on Nov 19, 2003 at 16:35 UTC
    my $a2count = $#array2; my @newarray; for (my $a1count = 0; $a1count<@array1; @a1count++ ) { push @newarray, @array1[$a1count] . @array2[$a2count--]; }


    Dave


    "If I had my life to live over again, I'd be a plumber." -- Albert Einstein

      Here's a similar way, without initializing either counter:

      push @new, $array1[$count1++].$array2[--$count2] while ($count1 < @array1 && -$count2 < @array2);
      By the way, your array accesses are using 1 element slices instead of direct element access. Consider changing @array1[$a1count] to $array1[$a1count].

      kelan


      Perl6 Grammar Student

      davido Please refrain from wholesale rewriting of node content! Minor edits should at least be acknowledged, and total replacement of content should only be done in extreme circumstances (which I can not think of any at the moment). Update your nodes, stop just rewriting them. Please. This is not the first time you've changed a nodes content out from under me just before I posted a reply, rendering the reply, which could have been instructive both to yourself and to others, totally without context.

      A reply falls below the community's threshold of quality. You may see it by logging in.