-1

I have a hash like this:

{ ABC => [1, 2],
     1 => [11, 12,13,14],
     13 => [17,20] }

I want to generate a hash of hashes like this:

(ABC => { 1 => {11 => {},
                12 => {},
                13 => { 17 => {}
                        20 = {} },
                14 => {}
               },
          2 => {}
        }

)

The above hash is nothing but a tree with a root node and further child nodes.

I understand we have to use recursion to check child nodes for every parent node. I have looked at the question previously asked here. I am unable to understand how during recursion specific node's data is stored under its particular parent key. In other words how can hash of hashes be populated recursively ?

Appreciate any pointers or explanation.

Thanks for your time

Community
  • 1
  • 1
Sashi Kiran Challa
  • 885
  • 1
  • 11
  • 21
  • 1
    Your requirements are underspecified. What happened to `2`? How do can one tell `ABC` is the root (since hashes aren't ordered)? – ikegami Aug 07 '12 at 19:09
  • 1
    @ikegami: One reason why `ABC` must be the root is because it alone among the top-level keys does not appear as a child (value) anywhere. And it looks like the missing `2` was an error that has now been fixed. – j_random_hacker Aug 09 '12 at 12:21

3 Answers3

3

The real problem is that you don't really know what you want.

 {ABC => 1 => 11 => {}
     => 1 => 12 => {}
     => 1 => 13 => 17 => {}
                => 20 = {}
     => 1 => 14 => {}
} 

is just a really weird way of writing

{
   ABC => "1",
   11  => {},
   1   => "12",
   {}  => "1",
   13  => "17",
   {}  => "20",
   {}  => "1",
   14  => {},
}

That makes no sense. I think you actually want

{
   ABC => {
      1 => {
         11 => {},
         12 => {},
         13 => {
            17 => {},
            20 => {},
         },
         14 => {},
      },
   },
}

Now that you know what you want, you should take a stab at implementing it.

ikegami
  • 322,729
  • 15
  • 228
  • 466
  • @Axeman, `{ }` does not return a constant string. It doesn't even return a string. – ikegami Aug 07 '12 at 21:15
  • I think it's mostly clear what the OP wants if you follow his link. – mob Aug 07 '12 at 22:06
  • @Axeman, Nope, it doesn't. The result gets stringified when used as a key, but that has nothing to do with anything being discussed here. all these posts are offtopic and should be deleted. – ikegami Aug 08 '12 at 04:29
  • @mob, Clear to us. Apparently not clear to the OP. That's why he couldn't even start to implement this. – ikegami Aug 08 '12 at 04:31
1

You can use the code I defined here: How can I merge several hashes into one hash in Perl?

having defined @hash_list so:

my @hash_list 
    = { map { ref() eq 'ARRAY' ? { map {; $_ => {} } @$_ } : $_ } 
        %{{ ABC => [1, 2]
          ,  1  => [11, 12,13,14]
          , 13  => [17,20] 
          }}
      };
Community
  • 1
  • 1
Axeman
  • 29,194
  • 2
  • 42
  • 98
  • It doesn't, if you "use the code I defined [at the link]", plugging in `@hash_list` as defined above. `{ ABC => { '1' => { '11' => {}, '12' => {}, '13' => { '17' => {}, '20' => {} }, '14' => {} }, '2' => {} } } ` – Axeman Aug 08 '12 at 12:23
1
#!/usr/bin/env perl

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

my %data = (
    ABC => [1, 2],
     1  => [11, 12, 13, 14],
     13 => [17, 20] 
);
my %hash;

sub modify_hash {
    my ($base, $ref) = @_;
    for my $k (keys %$ref) {
        if (exists $base->{$k}) {
            $ref->{$k} = $base->{$k};
            delete $base->{$k};
        }
        modify_hash($base, $ref->{$k});
    }
}

map { %{$hash{$_}} = map { $_ => {}; } @{$data{$_}}; } keys %data;
map { modify_hash(\%hash, $hash{$_}); } keys %hash;
print Dumper(\%hash);

output:

$VAR1 = {
          'ABC' => {
                     '1' => {
                              '11' => {},
                              '13' => {
                                        '17' => {},
                                        '20' => {}
                                      },
                              '12' => {},
                              '14' => {}
                            },
                     '2' => {}
                   }
        };
cdtits
  • 1,128
  • 6
  • 7