Perl nesting hash of hashes

subramanian picture subramanian · Mar 24, 2013 · Viewed 23.9k times · Source

I'm having some trouble figuring out how to create nested hashes in perl based on the text input.

i need something like this

my % hash = {
key1 => \%inner-hash,
key2 => \%inner-hash2
}

However my problem is I don't know apriori how many inner-hashes there would be. To that end I wrote the following piece of snippet to test if a str variable can be created in a loop and its reference stored in an array and later dereferenced.

{
    if($line =~ m/^Limit\s+$mc_lim\s+$date_time_lim\s+$float_val\s+$mc\s+$middle_junk\s+$limit  \s+$value/) {
        my $str = $1 . ' ' . $2 . ' ' . $7;
        push (@test_array_reference, \$str);
     }
}
foreach (@test_array_reference) {  
    say $$_;
}

Perl dies with a not a scalar run-time error. I'm a bit lost here. Any help will be appreciated.

Answer

Jared picture Jared · Mar 24, 2013

To answer your first (main?) question, you don't need to know how many hashes to create if you walk through the text and create them as you go. This example uses words of a string, delimited by spaces, as keys but you can use whatever input text for your purposes.

my $text = 'these are just a bunch of words';
my %hash;

my $hashRef = \%hash;           # create reference to initial hash
foreach (split('\s', $text)){
    $hashRef->{$_} = {};        # create anonymous hash for current word
    $hashRef = $hashRef->{$_};  # walk through hash of hashes
}

You can also refer to any arbitrary inner hash and set the value by,

$hash{these}{are}{just}{a}{bunch}{of}{words} = 88;
$hash{these}{are}{just}{a}{bunch}{of}{things} = 42;
$hash{these}{things} = 33;

To visualize this, Data:Dumper may help,

print Dumper %hash;

Which generates,

$VAR1 = 'these';
$VAR2 = {
          'things' => 33,
          'are' => {
                     'just' => {
                                 'a' => {
                                          'bunch' => {
                                                       'of' => {
                                                                 'things' => 42,
                                                                 'words' => 88
                                                               }
                                                     }
                                        }
                               }
                   }
        };