1

I have a perl HOH (hash of hash) wherein i have serial numbers 1,2,3.... so on and directory paths with associated counter values. Could anyone please suggest a way in which i can merge the duplicate internal paths (e.g, /usr/lib , /bin/ ) to a form a new hash with addition of the values?

Sample HOH:

$VAR1 = {
          '1' => {
                   '/usr/lib' => 18
                 },
          '3' => {
                   '/bin/' => '3'
                 },
          '4' => {
                   '/usr/lib' => 12
                 },
          '2' => {
                   '/bin/' => '6'
                 },
          '5' => {
                   '/dev/' => '2'
                 },
          '6' => {
                   '/tmp/' => '8'
                 }
        };

Final output requirement i am looking for is a simple hash with combined values. No need of serial numbers:

$VAR1 = {
              '/usr/lib' => '30',
              '/bin/' => '9',
              '/dev/' => '2',
              '/tmp/' => '8'
              
        };

3 Answers 3

1

Try

sub aggregate_counts {
    my $HOH = shift;
    my %out;
    for my $h (values %$HOH) {
        for my $k ( keys %$h) {
            $out{$k} += $h->{$k};
        }
    }
    \%out
}

Use this subroutine like aggregate_counts($hoh) to get hash reference in required format.

Complete Script for testing:

use strict;
use warnings;
sub aggregate_counts {
    my $HOH = shift;
    my %out;
    for my $h (values %$HOH) {
        for my $k ( keys %$h) {
            $out{$k} += $h->{$k};
        }
    }
    \%out
}

my
$VAR1 = {
          '1' => {
                   '/usr/lib' => 18
                 },
          '3' => {
                   '/bin/' => '3'
                 },
          '4' => {
                   '/usr/lib' => 12
                 },
          '2' => {
                   '/bin/' => '6'
                 },
          '5' => {
                   '/dev/' => '2'
                 },
          '6' => {
                   '/tmp/' => '8'
                 }
        };


use Data::Dumper;

print Dumper(aggregate_counts($VAR1))

Output:

$VAR1 = {
          '/dev/' => '2',
          '/tmp/' => '8',
          '/bin/' => 9,
          '/usr/lib' => 30
        };
Sign up to request clarification or add additional context in comments.

2 Comments

@ikegami I've modified the answer keeping your suggestions in mind. Can you clarify when is an uninitialised value in addition warning triggered? I used exists to avoid that.
Post/pre-inc/dec, += and -= don't care. Looks like |= and ^= don't either (but &= does).
1

This could help you:

use strict; use warnings;
use Data::Dumper;

my %hash = (
'1' => {
       '/usr/lib' => 18
     },
'3' => {
       '/bin/' => '3'
     },
'4' => {
       '/usr/lib' => 12
     },
'2' => {
       '/bin/' => '6'
     },
'5' => {
       '/dev/' => '2'
     },
'6' => {
       '/tmp/' => '8'
     }
);

my %result;

foreach my $key (keys %hash){
    foreach my $inner (keys %{$hash{$key}}) {
        $result{$inner} += $hash{$key}{$inner};
    }
}

print Dumper(\%result);

Output:

$VAR1 = {
          '/usr/lib' => 30,
          '/bin/' => 9,
          '/dev/' => 2,
          '/tmp/' => 8
        };

Note: Please post your code as well in the question while asking for a help in SO.

Comments

1

You don't care about the keys of the outer hash. So let's start with values(%$VAR1):

{ '/usr/lib' => 18 },
{ '/bin/' => '3' },
{ '/usr/lib' => 12 },
{ '/bin/' => '6' },
{ '/dev/' => '2' },
{ '/tmp/' => '8' },

Hashes are great for grouping. We're going to iterate over the above list, then we're going to iterates over the elements of each of those hashes, using a hash to group them.

my %grouped;
for my $inner (values(%$VAR1)) {
   for my $key (keys(%$inner)) {
      my $val = $inner->{$key};
      $grouped{$key} += $val;
   }
}

And we're already done.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.