CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Two-dimensional Arrays

 



goober99
Novice

Sep 20, 2004, 11:12 AM

Post #1 of 4 (519 views)
Two-dimensional Arrays Can't Post

I've discovered a strange behavior of two-dimensional arrays. I am trying to find the shortest way around it. I'm calling it the "Two-dimensional Array Mystery," and it can be demonstrated with only a few lines of code:


Code
@Array1 = (['One', 'Two', 'Three'], ['Four', 'Five', 'Six']); 
@Array2 = @Array1;

$Array2[0][0] = 'ONE';
print "$Array1[0][0]\n";


Try to guess the outcome of this snippet of code. I would have guessed that One would have been printed, but rather ONE is printed. It seems that Array1 and Array2 have become "tied" together. Changes to one also occur to the other.

What makes this even stranger is that the same example using one-dimensional arrays, acts as you would expect. This behavior is unique to two-dimensional arrays. While I'm curious why Perl would be designed this way, my question is how to overcome it easily.

This snippet is a slightly modified version from a much larger script. In this script, Array2 needs to have all the same values as Array1. The script makes some changes to the values in Array2. My problem is that later in the script, I access Array1, and I need the original values, but they have changed with the values in Array2.

Of course, I could create a loop that pushes each value from Array1 onto Array2 thus not creating the "tie," but I'm sure there must be an easier way to overcome this strange behavior of two-dimensional arrays.

-Matthew Miller
http://www.swingthesickle.org

(This post was edited by goober99 on Sep 20, 2004, 1:14 PM)


davorg
Thaumaturge / Moderator

Sep 21, 2004, 1:17 AM

Post #2 of 4 (511 views)
Re: [goober99] Two-dimensional Arrays [In reply to] Can't Post

Perl doesn't really support two-dimensional arrays (or, indeed, anything other than one-dimensional arrays) and you're getting burnt by that fact.

What you actually have in @Array1 is two references to anonymous arrays. When you assign @Array1 to @Array2, then the values in @Array1 are copied to @Array2. But the values in @Array1 are these references, so @Array2 ends up containing the same references to the same two anonymous arrays. So when you update one of these arrays via the references in @Array1, it's no surprise that when you access the same array via the values in @Array2 you see the same changes reflected.

This may be clearer if you print out the contents of @Array1 and @Array2.


Code
@Array1 = (['One', 'Two', 'Three'], ['Four', 'Five', 'Six']); 
@Array2 = @Array1;

print "@Array1\n@Array2\n";


This is the output I get:


Code
ARRAY(0x9d72c28) ARRAY(0x9d72b44) 
ARRAY(0x9d72c28) ARRAY(0x9d72b44)


Which shows that the same anonymous arrays are referenced from both of your arrays.

To see what you really want to do, read the answer to the FAQ How do I print out or copy a recursive data structure? which recommends using the "dclone" function from the Storable module.


Code
use Storable qw(dclone); 

@Array1 = (['One', 'Two', 'Three'], ['Four', 'Five', 'Six']);
@Array2 = @{ dclone(\@Array1) };

print "@Array1\n@Array2\n";


This gives


Code
ARRAY(0x8967c28) ARRAY(0x8967b44) 
ARRAY(0x89dc328) ARRAY(0x89dc364)


Which shows that we now have _new_ copies of the arrays.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


goober99
Novice

Sep 21, 2004, 6:50 AM

Post #3 of 4 (509 views)
Re: One Line Solution [In reply to] Can't Post

Thanks for the reply, and you helped me to understand what was going on, but I have now discovered a solution that only requires one line.

I replace


Code
@Array2 = @Array1;


with


Code
@Array2 = map { [ @{$_} ] } @Array1;


and it works fine.

-Matthew Miller
http://www.swingthesickle.org


davorg
Thaumaturge / Moderator

Sep 21, 2004, 7:00 AM

Post #4 of 4 (507 views)
Re: [goober99] One Line Solution [In reply to] Can't Post

Well, that works for 2-dimensional arrays, but you get back to the same problem if you go to 3 or more dimensions.

My solution works for all data structures of any complexity.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives