471,092 Members | 2,192 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,092 software developers and data experts.

Problem Copying Hash of Arrays (REUSED_ADDRESS)

Hello,

Consider this
Expand|Select|Wrap|Line Numbers
  1.  
  2. use strict;
  3. use Data::Dumper;
  4.  
  5. my %hash1=(a=>[1,1],
  6.         b=>[2,2],
  7.         c=>[3,3],);
  8.  
  9. my %hash2=%hash1;
  10.  
  11. $hash1{a}[0]=10;
  12.  
  13. print Dumper(%hash2);
  14.  
The problem is that when copying %hash1 into %hash2, the values of %hash2 are just a references to
the SAME arrays in %hash1, so changing an array element in %hash1 changes the respective element
in the new %hash2. But I want to store the old value of %hash1 into %hash2.
In a first attempt to solve that problem, I come with that :
Expand|Select|Wrap|Line Numbers
  1. use Data::Dumper;
  2. use strict;
  3. my %hash1=(a=>[1,1],
  4.         b=>[2,2],
  5.         c=>[3,3],);
  6.  
  7. my %hash2=();
  8. while ( my ($key,$val)= each %hash1) {
  9.   my @arr=@{$val};
  10.   $hash2{$key}=\@arr;
  11. }
  12.  
  13. $hash1{a}[0]=10;
  14. print Dumper(%hash2);
  15.  
but it's quite ugly.
I've also found that can surround the problem by assigning not a new value to the array (see: $hash1{a}[0]=10; )
but assigning a whole new array like this : $hash1{a}=[10,10];

But I still can't understand why the arrays are "copied" with the same address into %hash2 and
how I can store a %HoA into another %Hoa ...

please help
Feb 5 '07 #1
3 6112
miller
1,089 Expert 1GB
This is basically functioning as it shoud. If you want complete clones of each of the data structures inside the %hash, then you'll have to copy each of them. The easiest way to accomplish this would be to make a subroutine that recursively operated on arrays and unreferenced each element. The only function that it's important to be familiar with to accomplish this is ref.

http://perldoc.perl.org/functions/ref.html

Here is the code and function that I quickly through together from your example.

Expand|Select|Wrap|Line Numbers
  1. use strict;
  2. use Data::Dumper;
  3.  
  4. my %hash = (
  5.     a    => [1,1],
  6.     b    => [2,2],
  7.     c    => [3,3],
  8. );
  9.  
  10. my %copy = %hash;
  11. my %clone = clone(%hash);
  12.  
  13. $hash{a}[0]=10;
  14.  
  15. print 'copy - ' . Dumper(\%copy);
  16. print 'clone - ' . Dumper(\%clone);
  17.  
  18.  
  19. sub clone {
  20.     map { ! ref() ? $_ : ref eq 'HASH' ? {clone(%$_)} : ref eq 'ARRAY' ? [clone(@$_)] : die "$_ not supported" } @_;
  21. }
  22.  
Also, just as a stylistic note, I find it much better if I only pass scalars to Dumper. In this instance that means passing a reference to the hashes you want to explore instead of the hashes themselves. You'll find the output to be much cleaner in my opinion.

Good luck.
Feb 5 '07 #2
KevinADC
4,059 Expert 2GB
another possibility:

Expand|Select|Wrap|Line Numbers
  1. use Data::Dumper;
  2. use Storable qw/dclone/;
  3. my %hash1=(a=>[1,1],
  4.         b=>[2,2],
  5.         c=>[3,3],);
  6.  
  7. my $hash2 = dclone(\%hash1);
  8.  
  9. $hash1{a}[0]=10;
  10.  
  11. print Dumper(\$hash2,\%hash1);
$hash2 will be a copy only of %hash1, but the structure of $hash2 is a little different in that $hash2 is a reference to a hash of arrays instead of a hash of arrays like %hash1 is.
Feb 5 '07 #3
Really appreciate your help... Thanks
Feb 5 '07 #4

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

3 posts views Thread by Markus Dehmann | last post: by
2 posts views Thread by shan_rish | last post: by
3 posts views Thread by railrulez | last post: by
4 posts views Thread by sonjaa | last post: by
reply views Thread by berwiki | last post: by
3 posts views Thread by ipointer | last post: by
1 post views Thread by =?Utf-8?B?Y3JhbmtlX2JveQ==?= | last post: by
1 post views Thread by =?Utf-8?B?c3BhaW5jYw==?= | last post: by
3 posts views Thread by itsmenarwal | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.