Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to deep copy a hash of hashes in Perl? [duplicate]

Tags:

deep-copy

perl

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) 
like image 851
Oesor Avatar asked Oct 09 '09 22:10

Oesor


People also ask

How do I copy a hash in Perl?

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.

What are the ways in which hash values can be manipulated?

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.

How will you create hashes in Perl explain with an example?

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 “$”.


1 Answers

use Storable qw(dclone); $group2 = dclone(\%group); 
like image 86
codehead Avatar answered Sep 20 '22 16:09

codehead