Jimmy Koerting
Jimmy Koerting

Reputation: 1241

Copy hash of hash (HoH) into a key/value pair and back in perl

I wonder if this is possible and how: I have a hash of hashes %backup and I want to save it in a value of another hash of hashes, like this:

$globsessions{$session}{'backup'} = %backup;

and later on (of course) I want it back like this:

%backup = $globsessions{$session}{'backup'};

This is not working and I just lost a little here (maybe to less coffee...). The %globsessions is global in my app and should be reused.

Many thanks in advance for your help!

Edit: Using references as Neil suggested does not work, since the child owning %backup is dead the next time I need the data thus the reference is not valid anymore. So I have more a child/parent problem than a 'copy a hashofhashes' problem. But the solution from Neil for that is properly!

Upvotes: 3

Views: 1265

Answers (2)

Neil Slater
Neil Slater

Reputation: 27207

You have close to the right syntax, but cannot assign a hash directly as a value in another hash. Hash values are scalars. So you need to turn your %backup into a reference.


If you want to copy the data into the new location:

$globsessions{$session}{'backup'} = { %backup };

This is a shallow copy of contents of %backup - it is less efficient, but prevents over-writing keys or values in the original variable. Caveat: It doesn't copy deep structures, so if a value in %backup is another hash or array reference, then it could be modified. Use Storable's dclone if you want to make a deep copy.


If you want to maintain a reference back to the original hash:

$globsessions{$session}{'backup'} = \%backup;

This stores a reference to %backup - it is more efficient, but if you set $globsessions{$session}{'backup'}{'foo'} = 'bar' then you also change the original %backup


To copy data back to %backup:

A shallow copy will probably suffice:

%backup = %{ $globsessions{$session}{'backup'} };

Or using a deep copy, which is slower but safer with data, and requires Storable:

%backup = %{ dclone( $globsessions{$session}{'backup'} ) };

Upvotes: 7

Borodin
Borodin

Reputation: 126742

I suggest you use the Clone module to duplicate the hash of hashes.

You need to dereference the stored data to move it back to a hash, but it would be more efficient to work with the stored reference.

Like this

use strict;
use warnings;

use Clone 'clone';

$globsessions{$session}{backup} = clone(\%backup);

then retrieve it using

my $backup = $globsessions{$session}{backup}

or, less efficiently, you can replicate the top-level hash elements using

my %backup = %{ $globsessions{$session}{backup} }

or, if you need another complete separate copy that you can modify without affecting the backup in %globsessions

my %backup = %{ clone($globsessions{$session}{backup}) }

Note that these code fragments are untested as I have no access to a Perl compiler at the moment.

Upvotes: 2

Related Questions