Dynamically create hash of hash with array ref values

660 views Asked by At

I want to dynamically create a structure as follows:

{  
   edition1 => {  
                 Jim => ["title1", "title2"],  
                 John => ["title3", "title4"],  
              },  
  edition2 => { 
                 Jim => ["titleX",],  
                 John => ["titleY,],  
              }  etc
}  

I am confused on how I do it.
Basically I am thinking in the terms of:

my $edition = "edition1";  
my $author = "Jim";  
my $title = "title1";  
my %main_hash = ();  

${$main_hash{$edition}} ||= {};   

${$main_hash{$edition}}->{$author} ||= [];     

push @{{$main_hash{$edition}}->{$author}} , $title;   

But somehow I am not sure how I can do it properly and the syntax seems very complex.
How can I achieve what I want in a nice/clear manner?

1

There are 1 answers

4
Borodin On BEST ANSWER

You have made it rather hard for yourself. Perl has autovivication which means it will magically create any necessary hash or array elements for you if you use them as if they contained data references

Your line

push @{{$main_hash{$edition}}->{$author}} , $title;

is the closest you came, but you have an extra pair of braces around $main_hash{$edition} which attempts to create an anonymous hash with $main_hash{$edition} as its only key and undef as the value. You also don't need to use the indirection arrow between closing and opening brackets or braces

This program shows how to use Perl's facilities to write this more concisely

use strict;
use warnings;

my %data;

my $edition = "edition1";
my $author  = "Jim";
my $title   = "title1";

push @{ $data{$edition}{$author} }, $title;

use Data::Dump;
dd \%data;

output

{ edition1 => { Jim => ["title1"] } }