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

Hello all Perl monks - I am trying to copy an array of arrays. It is somehow still using the references. I want to alter the copy but leave the original intact. So far I have had very little success. Here is a little sample, can anyone tell me what I am doing wrong. I am about ready to pull my hair out. :-) I know it has to be something simple (or maybe I hope so).

#!/usr/local/bin/perl my @myarray = ([(1..7)],[(1..7)]); my $myarrayref = \@myarray; my @newArray = ( 0, @{$myarrayref}[1..$#{$myarrayref}]); for my $len (0..$#{$myarrayref}) { print "PRE Alteration: @{$$myarrayref[$len]}\n"; } alt_ref($myarrayref); for my $len (0..$#{$myarrayref}) { print "POST Alteration: @{$$myarrayref[$len]}\n"; } sub alt_ref { my ($arr_ref )= @_; my @new_arr = @{$arr_ref}; for my $i (0..$#new_arr) { pop(@{$new_arr[$i]}); } for my $len (0..$#new_arr) { print "DURING Alteration: @{$new_arr[$len]}\n"; } }

The OUTPUT is such:

PRE Alteration: 1 2 3 4 5 6 7
PRE Alteration: 1 2 3 4 5 6 7
DURING Alteration: 1 2 3 4 5 6
DURING Alteration: 1 2 3 4 5 6
POST Alteration: 1 2 3 4 5 6
POST Alteration: 1 2 3 4 5 6

I want the POST Alteration lines to be the same as the PRE Alteration lines(thus leaving the original unaltered. Thanks in advance.

Mike

Replies are listed 'Best First'.
Re: using arrays of arrays
by kcott (Archbishop) on Nov 05, 2010 at 06:15 UTC

    Your problem here is that you're taking a reference to the array and then dereferencing it in the subroutine getting back the original array.

    Instead of

    my $myarrayref = \@myarray;

    try doing

    my $myarrayref = [@myarray];

    Take a look at perlref for a discussion of how this works; if that seems a little advanced for you, try the tutorial: perlreftut.

    -- Ken

Re: using arrays of arrays
by ikegami (Patriarch) on Nov 04, 2010 at 22:56 UTC

    I want to alter the copy but leave the original intact.

    You never use the copy after making it. Did you mean to pass \@newArray to alt_ref?

Re: using arrays of arrays
by CountZero (Bishop) on Nov 05, 2010 at 00:43 UTC
    Have a look at Data::COW, it does the copying for you and is very frugal with memory.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: using arrays of arrays
by chrestomanci (Priest) on Nov 05, 2010 at 11:48 UTC

    If you are looking to create an exact copy of any perl data structure, then you can use the dclone() function from Storable.pm

    Obviously if you clone a big data structure that way it will take a while, and will burn a lot of memory, so if you are looking to change a small amount of a large data structure, you may want to consider a more advanced algorithm.

    Don't do what I did when I was a novice which is to write code like this:

    foreach my $key1 (keys %$foo) { foreach my $key2 (keys %{$foo->{$key1}}) { # etc.... $bar->[$idx1][$idx2]..[$idx5] = $foo->{$key1}{$key2}..{$key5};

Re: using arrays of arrays
by locked_user sundialsvc4 (Abbot) on Nov 05, 2010 at 11:39 UTC

    There are numerous modules (such as the ones already described), or Storable’s dcopy function, which can help you here.

    The essential problem here is that the easiest way to “copy a data structure” (or, that is to say, to think that you have done so...) involves the use of “references,” which are rather like “pointers” in other, more primitive languages.   Doing a deep copy, using any of the tools described, guarantees that you are left with a new data structure.

Re: using arrays of arrays
by JavaFan (Canon) on Nov 05, 2010 at 11:54 UTC
    Deep copying an array of arrays is a one-liner:
    my @copy = map {[@$_]} @original;