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

Hi Monks,

I have an array like this,
comp1-cmd1-test1 comp1-cmd1-test2 comp1-cmd2-test1 comp2-cmd1-test1 comp2-cmd1-test2 comp3-cmd1-test1
I would like to convert this to a hash like this,
%hoh = ( "comp1" => { "cmd1" => [ "test1", "test2" ], "cmd2" => [ "test1" ] }, "comp2" => { "cmd1" => [ "test1", "test2" ] }, "comp3" => { "cmd1" => [ "test1" ] }, );<br>
Can anyone of you please help me to get thru this. I found some perl modules in CPAN which is not elaborate to be used.
I just started developing it like this,

%hoh = (); foreach my $temp (sort @{$arr1} ) { my ($comp, $cmd, $test) = split(/\-/, $temp); $hoh{$temp} = { comp => $comp, cmd => $cmd, test => $test, }; }
But this is not sufficient to get it the way I need.

Hoping to get the solution here.

Thanks
Senthil

20051021 Janitored by Corion: Added code tags

Replies are listed 'Best First'.
Re: generating hash from array
by chester (Hermit) on Oct 21, 2005 at 15:27 UTC
    This relies a lot on auto-vivification:

    use warnings; use strict; use Data::Dumper; my %hoh; while(<DATA>) { chomp( my @fields = split /-/, $_ ); push @{ $hoh{$fields[0]}->{$fields[1]} }, $fields[2] } print Dumper \%hoh; __DATA__ comp1-cmd1-test1 comp1-cmd1-test2 comp1-cmd2-test1 comp2-cmd1-test1 comp2-cmd1-test2 comp3-cmd1-test1

    Update: added chomp

Re: generating hash from array
by davidrw (Prior) on Oct 21, 2005 at 15:31 UTC
    This should work for you .. You were on the right track, but looks like you wanted a hash of arrays intead of a hash of a hash which is what your code was doing.
    use strict; use warnings; my %h = (); while(<DATA>){ chomp; my ($comp,$cmd,$test) = split /-/, $_; push @{$h{$comp}->{$cmd}}, $test; } use Data::Dumper; print Dumper \%h; __DATA__ comp1-cmd1-test1 comp1-cmd1-test2 comp1-cmd2-test1 comp2-cmd1-test1 comp2-cmd1-test2 comp3-cmd1-test1
Re: generating hash from array
by amw1 (Friar) on Oct 21, 2005 at 15:37 UTC
    Is this what you wanted?
    Note: this does handle the command->test thing you asked for as well. Will also prevent duplicates.
    #!/usr/bin/perl + use strict; use Data::Dumper; my @arr = qw(comp1-cmd1-test1 comp1-cmd1-test2 comp1-cmd2-test1 comp2- +cmd1-test1 comp2-cmd1-test2 comp3-cmd1-test1); my $ret_struct; foreach my $element (@arr) { my ($comp, $cmd, $test) = split(/\-/, $element); push(@{$ret_struct->{$comp}{$cmd}}, $test) unless(grep(/$test/, @{$ret_struct->{$comp}{$cmd}})); push(@{$ret_struct->{$cmd}}, $test) unless(grep(/$test/, @{$ret_struct->{$cmd}})); } print Dumper($ret_struct);

    Here is the output

    $VAR1 = { 'cmd2' => [ 'test1' ], 'comp2' => { 'cmd1' => [ 'test1', 'test2' ] }, 'comp3' => { 'cmd1' => [ 'test1' ] }, 'cmd1' => [ 'test1', 'test2' ], 'comp1' => { 'cmd2' => [ 'test1' ], 'cmd1' => [ 'test1', 'test2' ] } };
      Thanks a LOTTTTT, Chester, Davidrw, AMW1.

      That's really a gr8 stuff!!!!!

      Thanks
      Senthil
Re: generating hash from array
by pg (Canon) on Oct 21, 2005 at 17:20 UTC

    Change your data structure a little bit (a better one, so that all levels are consistant), you can use some more generic code:

    use warnings; use strict; use Data::Dumper; my @array = qw/ comp1-cmd1-test1 comp1-cmd1-test2 comp1-cmd2-test1 comp2-cmd1-test1 comp2-cmd1-test2 comp3-cmd1-test1/; my $hash = {}; for my $element (@array) { my @stuffs = split /-/, $element; insert($hash, \@stuffs); } print Dumper($hash); sub insert { my ($hash, $stuffs) = @_; my $first_element = shift @$stuffs; $hash->{$first_element} = {} if (!defined($hash->{$first_element}) +); insert($hash->{$first_element}, $stuffs) if (@$stuffs); }

    This gives:

    $VAR1 = { 'comp2' => { 'cmd1' => { 'test1' => {}, 'test2' => {} } }, 'comp3' => { 'cmd1' => { 'test1' => {} } }, 'comp1' => { 'cmd2' => { 'test1' => {} }, 'cmd1' => { 'test1' => {}, 'test2' => {} } } };
Re: generating hash from array
by rsennat (Beadle) on Oct 21, 2005 at 17:48 UTC
    Hi Chester, Davidrw, AMW1, PG

    Thanks a LOTTTTT,

    That's really a gr8 stuff!!!!!

    Thanks
    Senthil