http://www.perlmonks.org?node_id=593360

utku has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I cannot figure out how to create a HoH (or even HoHoH) from a file in + following format: path start end delay ---------------------------------------------------------- my_path /path/3434/some_txt wodo -445 your_path /path/3434/some_txt wodo_modo 41 my_path2 /path/232/wge45 wodo_modo 240 my_path /t43/annow23x /a/b/c/43 NA ... Each line above corresponds a "record" and belongs to a "path". So a "path" can include several "records". Above, "my_path" includes 2 records, ie. 1st and 4th lines. I just want to store all lines above into a single hash in the form of: $db_hash{$path}{<index_for_corresponding_path>}{START} $db_hash{$path}{<index_for_corresponding_path>}{END} $db_hash{$path}{<index_for_corresponding_path>}{DELAY} For ex, 1st line will be: $db_hash{my_path}{1}{START} = "/path/3434/some_txt" $db_hash{my_path}{1}{END} = "wodo" $db_hash{my_path}{1}{DELAY} = "-445" ... $db_hash{my_path}{2} must be generated from the 4th line and so forth. The number of "paths" are determined during runtime, thus I must also determine indices for each "path" on runtime. The number of members in each "path" can be different. My question is, how to create index for each unique $path key? I shall create a separate array of indices, shan't I?

Replies are listed 'Best First'.
Re: Creating members of hash of hashes parallelly
by japhy (Canon) on Jan 07, 2007 at 02:09 UTC
    You don't want a hash in that middle level, then, you want an array: $db_hash{$path}[$idx]{$key}. To do that, you'd do:
    while (<>) { my ($path, $start, $end, $delay) = split; # or however you get them push @{ $db_hash{$path} }, { START => $start, END => $end, DELAY => $delay, }; }

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: Creating members of hash of hashes parallelly
by liverpole (Monsignor) on Jan 07, 2007 at 02:17 UTC
    Hi utku,

    If I understand you correctly, the following should work:

    use strict; use warnings; use Data::Dumper; my %db_hash; while (<DATA>) { chomp; my ($path, $start, $end, $delay) = split /\s+/, $_; # Get index for this path (if undefined, set it to 1) my $index = ++$db_hash{$path}{'index'}; $db_hash{$path}{$index}{START} = $start; $db_hash{$path}{$index}{END} = $end; $db_hash{$path}{$index}{DELAY} = $delay; } printf "Contents of db_hash => %s\n", Dumper(\%db_hash); __DATA__ my_path /path/3434/some_txt wodo -445 your_path /path/3434/some_txt wodo_modo 41 my_path2 /path/232/wge45 wodo_modo 240 my_path /t43/annow23x /a/b/c/43 NA

    Which will yield:

    Contents of db_hash => $VAR1 = { 'my_path2' => { '1' => { 'START' => '/path/232/wge45', 'DELAY' => '240', 'END' => 'wodo_modo' }, 'index' => 1 }, 'my_path' => { '1' => { 'START' => '/path/3434/some_txt', 'DELAY' => '-445', 'END' => 'wodo' }, 'index' => 2, '2' => { 'START' => '/t43/annow23x', 'DELAY' => 'NA', 'END' => '/a/b/c/43' } }, 'your_path' => { '1' => { 'START' => '/path/3434/some_txt', 'DELAY' => '41', 'END' => 'wodo_modo' }, 'index' => 1 } };

    Update:  Changed print to the printf it was supposed to be (which reveals a mistake I make all the time).  Thanks ysth, for catching that.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      Thank you very much folks, you have enlightened the points I could not figure out.

      Both solutions (HoAoH by robotics and japhy; HoHoH by liverpole) worked.
      HoHoH solution has the drawback that the interpreter generates an initialization error during initialization of indices.

      Thanks again for your ultra-fast answers!
        HoHoH solution has the drawback that the interpreter generates an initialization error during initialization of indices.
        How so? Can you show us what you mean?
Re: Creating members of hash of hashes parallelly
by roboticus (Chancellor) on Jan 07, 2007 at 02:07 UTC
    The last sentence in your question provides the clue: You need an index, so rather than a HoH or HoHoH, what you really want is a HoAoH. The first H key being your path, the A being an array of your records, the last H being your attributes.

    Roboticus