Question

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.

Was it helpful?

Solution

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
                                                               }
                                                     }
                                        }
                               }
                   }
        };

OTHER TIPS

my $hashref = { hash1 => { key => val,... },
                hash2 =>  { key => val,..}  };

also you may want to use the m//x modifier with your regex, its barely readable as it is.

Creating a hash of hashes is pretty simple:

my %outer_hash = {};

Not entirely necessary, but this basically means that each element of your hash is a reference to another hash.

Imagine an employee hash keyed by employee number:

$employee{$emp_num}{first} = "Bob";
$employee{$emp_num}{last}  = "Smith";
$employee{$emp_num}{phones}{cell} = "212-555-1234";
$employee{$emp_num}{phones}{desk} = "3433";

The problem with this notation is that it gets rather hard to read after a while. Enter the arrow notation:

$employee{$emp_num}->{first} = "Bob";
$employee{$emp_num}->{last}  = "Smith";
$employee{$emp_num}->{phones}->{cell} = "212-555-1234";
$employee{$emp_num}->{phones}->{desk} = "3433";

The big problem with complex structures like this is that you lose the use strict ability to find errors:

$employee{$emp_num}->{Phones}->{cell} = "212-555-1234";

Whoops! I used Phones instead of phones. When you start using this type of complex structure, you should use object oriented syntax. Fortunately, the perlobj tutorial is pretty easy to understand.

By the way, complex data structure handling and the ability to use object oriented Perl puts you into the big leagues. It's the first step into writing more powerful and complex Perl.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top