954,523 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

how to loop through multi-level hash structure

I have the following hashed structure

$chainStorage{$R1}{$S1}{$C1}{@A1}
$chainStorage = { 'ACB' => { 'E' => '06' => [100, 200, 95] 'B' => '23' => [20, 1000, 05, 30] }, 'AFG' => { 'C' => '24' => [18, 23, 2300, 3456] }, 'HJK' => { 'A' => '12' => [24, 25, 3200, 5668] 'D' => '15' => [168] } };


For example, ACB corresponds to two arrays,[100, 200, 95] and [20, 1000, 05, 30];
while ‘E’ corresponds to [100, 200, 95] only.

Right now, I need to add all of the elements in the array corresponding to the first-level key, e.g., ‘ACB’, together.

In other words, in another hash structure, I want ACB corresponds to
100+200+95 +20+1000+05+30 = 1450

How to implement this functionality over $chainStorage

winecoding
Junior Poster in Training
56 posts since Dec 2009
Reputation Points: 10
Solved Threads: 0
 

Use code tags instead of quote tags to preserve formatting.

The code you've posted doesn't describe the structure you've said it does. => is just syntactic sugar for a comma, so $chainStorage->{ACB} is

{
    E => '06',
    [100, 200, 95] => 'B',
    '23' => [20, 1000, 5, 30],
}


Assuming you meant the following (formatting added)...

$chainStorage = {
    ACB => {
        E => { '06' => [100, 200, 95] },
        B => { '23' => [20, 1000, 5, 30] },
    },
    AFG => {
        C => { '24' => [18, 23, 2300, 3456] },
    },
    HJK => {
        A => { '12' => [24, 25, 3200, 5668] },
        D => { '15' => [168] },
    },
};


... then you still have kind of an odd situation because your tertiary (third-layer) hashes never have more than one key and one value. If that's always the case it'd probably be better to think of a different way to store them. You might, for instance, make the tertiary key the first element of the list, like this:

ACB => {
        E => ['06', 100, 200, 95],
        B => ['23', 20, 1000, 5, 30],
    },

Then use something like this to add the elements:

my $href = $chainStorage->{ACB};

my $sum = 0;
foreach my $aref (values %$href) {
        my @ary = @$aref;
        @ary = @ary[1..$#ary]; # I had to slice the first element back out
        $sum += $_ foreach (@ary);
}

If you can't restructure your data like this, it'll be an extra step to pull the array out of the interior hashref, but that shouldn't be too much of a stretch... Without making unwarranted assumptions about your data structure, I can't give you any more, but maybe this is enough to go on.

Trentacle
Junior Poster in Training
72 posts since Dec 2010
Reputation Points: 110
Solved Threads: 20
 

Building on Trentacle 's first correction of your data structure you could try the following:

#!/usr/bin/perl;
use strict;
use warnings;
use Data::Dumper;

my $chainStorage = {
    ACB => {
        E => { '06' => [100, 200, 95] },
        B => { '23' => [20, 1000, 5, 30] },
    },
    AFG => {
        C => { '24' => [18, 23, 2300, 3456] },
    },
    HJK => {
        A => { '12' => [24, 25, 3200, 5668] },
        D => { '15' => [168] },
    },
};

my %results;

foreach my $flk(keys %$chainStorage){
    $results{$flk} = 0;
    
    foreach my $slk(keys $$chainStorage{$flk}){
        foreach my $tlk(keys $$chainStorage{$flk}{$slk}){
            foreach my $aref ($$chainStorage{$flk}{$slk}{$tlk}){
                foreach my $elem(@$aref){
                    $results{$flk} += $elem;
                }
            }
        }
    }
}

print Dumper(\%results);


Outputs $VAR1 = {
'AFG' => 5797,
'HJK' => 9085,
'ACB' => 1450
};

d5e5
Practically a Posting Shark
810 posts since Sep 2009
Reputation Points: 159
Solved Threads: 159
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: