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

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

This node falls below the community's threshold of quality. You may see it by logging in.
  • Comment on How to substitute the elements in an array without changing the original array.

Replies are listed 'Best First'.
Re: How to substitute the elements in an array without changing the original array.
by davido (Cardinal) on Dec 01, 2006 at 05:54 UTC

    I have a box of a dozen doughnuts. I want to eat three of them, and still have a full box with a dozen when I'm done.

    Solution? You need another box. ;)

    In Perl, you need two arrays; one is the original, and one will be the copy, on which you can perform whatever manipulations you wish, without affecting the original.

    my @array = qw/one two three four five/; my @copy = @array; shift @copy; print "Original: @array\n"; print "Copy: @copy\n";

    There are infinite other strategies, but your question is vague enough to make it impossible to focus on which strategy would be optimal.


    Dave

Re: How to substitute the elements in an array without changing the original array.
by ikegami (Patriarch) on Dec 01, 2006 at 06:04 UTC

    You want grep (to remove rows), map (to transform rows) or List::MoreUtils's apply (to transform rows).

    When using grep or map, don't change $_ unless you want to change the original array.

    apply is similar to map, but you can safely modify $_. The downside to using apply is that you're limited to 1:1 transformations (whereas map is extremely flexible).

    use List::MoreUtils qw( apply ); my @orig = qw( Just another Perl hacker ); my @grepped = grep { /^[A-Z]/ } @orig; my @mapped = map { uc } @orig; my @applied = apply { s/[aiueo]//ig } @orig; print("@orig\n"); # Just another Perl hacker print("@grepped\n"); # Just Perl print("@mapped\n"); # JUST ANOTHER PERL HACKER print("@applied\n"); # Jst nthr Prl hckr

    List::MoreUtils can easily be installed if you're using ActivePerl. Just type by ppm install List-MoreUtils at the prompt

Re: How to substitute the elements in an array without changing the original array. - map
by imp (Priest) on Dec 01, 2006 at 05:51 UTC
    See map.
    my @source = (1,2,3,4); my @dest = map { $_ * 2 } @source; print "@source\n"; print "@dest\n"; #Output: #1 2 3 4 #2 4 6 8
    my @source = ('bob', 'joe'); my @dest = map { $_ eq 'bob' ? ucfirst($_) : $_ } @source; print "@source\n"; print "@dest\n"; #Output: #bob joe #Bob joe
      @a=("sedam","medam","kadam","sadam"); for(@b=@a) { s/dam/lam/; } print "@b\n"; print "@a";
Re: How to substitute the elements in an array without changing the original array.
by shotgunefx (Parson) on Dec 01, 2006 at 06:19 UTC
    And to add to these fine comments for future reference, they only really apply to simple scalars (strings, numbers), array references, hash references, etc are a slightly trickier matter.

    You would need to make copies of the data itself and not just the references to the data

    -Lee
    "To be civilized is to deny one's nature."
Re: How to substitute the elements in an array without changing the original array.
by perladdict (Chaplain) on Dec 01, 2006 at 08:43 UTC
    hey, if u r trying to replace the strings by using s///operator,the below code will wok fine.
    #!/usr/bin/perl -w @a=("sedam","medam","kadam","sadam"); for(@b=@a) { s/dam/lam/; } print "@b\n"; print "@a";
Re: How to substitute the elements in an array without changing the original array.
by Firefly258 (Beadle) on Dec 02, 2006 at 00:46 UTC
    I tend to use a few tricks with map and grep to preserve the original array than to seek out and use something different.
    @new = map { ... } @{[ @original ]};
    or even
    @new = grep { local $_ = $_; ... } @original;
    If legibility (management overhead due to fussy boss) is a concern, I then choose to use an idomatic version of the for / do { ... } for loop.
    ... for @new = @original;
    or if you want multiple expressions within the loop..
    do { ...; ... } for @new = @original;


    perl -e '$,=$",$_=(split/\W/,$^X)[y[eval]]]+--$_],print+just,another,split,hack'er