Hello,
How can I create an anonymous hash from an existing hash?
For arrays, I use:
@x = (1, 2, 3);
my $y = [@x];
but I can't find how to do the same for a hash:
my %x = ();
my $y = ???;
Thanks
Hello,
How can I create an anonymous hash from an existing hash?
For arrays, I use:
@x = (1, 2, 3);
my $y = [@x];
but I can't find how to do the same for a hash:
my %x = ();
my $y = ???;
Thanks
If you have
my %hash = ...
then you can do
my $hashref = \%hash;
my $new_hash = { %existing_hash };
Note that this solution does not make a deep copy. Read brian's answer for explanation.
I think you need to be careful here. Consider the following hash:
my %hash = (1 => 'one',2 => 'two');
There are two ways you can get a reference from this:
my $ref = \%hash;
my $anon = {%hash};
$ref
is a reference to the original hash and can be used similarly to %hash
. $anon
is a reference to an anonymous copy of the original hash; it will have the same data but changing it won't change the original hash and vice versa.
So, for example, to start with both of these statements will have the same output
print $ref->{1},"\n";
> one
print $anon->{1},"\n";
> one
But if I change the original hash:
$hash{1} = "i";
They two print
statements would output different values:
print $ref->{1},"\n";
> i
print $anon->{1},"\n";
> one
There seem to be two things going on here, and the answers are split between answering two different possible questions.
If you want 1, do this:
my $hash_ref = { foo => 1, bar => 2 };
If you want 2, do this:
my %hash = ( foo => 1, bar => 2 );
# Then later
my $anon_copy_hash_ref = { %hash };
(The names are not meant for prime time.) My copy isn't ready for prime time either. See brian's post for a fuller, more precise discussion.
Why do you need an anonymous hash? Although the answers tell you various ways you could make an anonymous hash, we have no idea if any of them are the right solution for whatever you are trying to do.
If you want a distinct copy that you can modify without disturbing the original data, use dclone
from Storable, which comes with Perl. It creates a deep copy of your data structure:
use Storable qw(dclone);
my $clone = dclone \%hash;
Consider Dave Webb's answer, but with an additional layer of references. The value for the key of c
is another hash reference:
use Data::Dumper;
my %original = ( a => 1, b => 2, c => { d => 1 } );
my $copy = { %original };
print
"Before change:\n\n",
Data::Dumper->Dump( [ \%original], [ qw(*original) ] ),
Data::Dumper->Dump( [ $copy ], [ qw(copy) ] ),
;
$copy->{c}{d} = 'foo';
print
"\n\nAfter change:\n\n",
Data::Dumper->Dump( [ \%original], [ qw(*original) ] ),
Data::Dumper->Dump( [ $copy ], [ qw(copy) ] ),
;
By inspecting the output, you see that even though you have an anonymous hash, it's still linked to the original:
Before change:
%original = (
'c' => {
'd' => 1
},
'a' => 1,
'b' => 2
);
$copy = {
'c' => {
'd' => 1
},
'a' => 1,
'b' => 2
};
After change:
%original = (
'c' => {
'd' => 'foo'
},
'a' => 1,
'b' => 2
);
$copy = {
'c' => {
'd' => 'foo'
},
'a' => 1,
'b' => 2
};
A quick/easy way to achieve a deep copy:
use FreezeThaw qw(freeze thaw);
$new = thaw freeze $old;