Possible Duplicate:
What's the best way to make a deep copy of a data structure in Perl?
Before I start coding this myself and reinventing the wheel, how do you copy a hash of hashes without duplicating the hashrefs?
I'm reading a hash of hash of hashes via Config::General. i.e., the data structure is:
my %config = ( group => { item1 => { foo => 'value', bar => 'value', }, item2 => { foo => 'value', bar => 'value', }, item3 => { foo => 'value', bar => 'value', }, }, );
I then pull my group from the config by dereferencing it and change the contents at runtime prior to rewriting the config file:
my %group = %{$config{'group'}};
The problem is that I need to check to see if changes were made and make associated changes to the system's file structure. I can't do this by checking:
if ($group{'item1'}{'foo'} ne $config{'group'}{'item1'}{'foo'}) { ### Stuff! }
as $group{'item1'}
and $config{'group'}{'item1'}
are both the exact same hashref.
Now while it should be trivial to simply re-parse the config file, and compare the parsed copy from the disk against the edited version just before saving to disk, I'm sure there's a way to to a nested dereference of a complex data structure, copying the contents of the hash refs and not simply copying the references themselves. A cursory examination on CPAN doesn't turn anything up. What am I missing?
Benchmark
Got my answer:
#!/usr/bin/perl use Benchmark qw(:all) ; use Storable qw(dclone); use Clone qw(clone); my %config = ( group => { item1 => { foo => 'value', bar => 'value', }, item2 => { foo => 'value', bar => 'value', }, item3 => { foo => 'value', bar => 'value', }, }, ); my $ref = $config{'group'}; timethese(100000, { 'Clone' => sub { my %group = %{ clone $ref }}, 'Storable' => sub { my %group = %{ dclone $ref }}, });
results in:
Benchmark: timing 100000 iterations of Clone, Storable... Clone: 2 wallclock secs ( 2.26 usr + 0.01 sys = 2.27 CPU) @ 44052.86/s (n=100000) Storable: 5 wallclock secs ( 4.71 usr + 0.02 sys = 4.73 CPU) @ 21141.65/s (n=100000)
You can create a shallow copy of a hash easily: my $copy = { %$source }; The %$source bit in list context will expand to the list of key value pairs. The curly braces (the anonymous hash constructor) then takes that list an creates a new hashref out of it.
There are two ways to initialize a hash variable. One is using => which is called the fat arrow or fat comma. The second one is to put the key/value pairs in double quotes(“”) separated by a comma(,). Using fat commas provide an alternative as you can leave double quotes around the key.
In the above, there are two ways of defining or declaring hash in Perl. In the first syntax, we can see we have assigned a value to keys that are named and will be placed within the curly braces and this can be used when we want to declare each key-value pair one by one and the key is preceded by “$”.
use Storable qw(dclone); $group2 = dclone(\%group);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With