0

within a loop I retreive

  • An array (its length and data might change at each iteration)
  • 1 Data name
  • 1 Data value

And I would like to create a hash of hash having as structure the array and set at the end the data retreived.

exemple if I have:

@array = ('a','b','c');
$dataname = 'my data';
$datavalue = '123';

I would like to have a hash as below:

%hash = (
     a => {
           b => {
                 c => {
                       'my data' => '123'
                      }
                }
          }
          );

But i didn't find anywhere how to do it.

1
  • 1
    Take a look at Data::Diver Commented Feb 8, 2017 at 16:38

2 Answers 2

3
use Data::Diver qw( DiveVal );

DiveVal(\%hash, map \$_, @array, $dataname) = $datavalue;

Alternatively,

sub DiveVal :lvalue {
   my $p = \shift;
   $p = \( $$p->{$_} ) for @_;
   $$p
}

DiveVal(\%hash, @array, $dataname) = $datavalue;
Sign up to request clarification or add additional context in comments.

4 Comments

@Hunter McMillen, Explanation of the above code. In particular, read "The extra level of indirection has many benefits" section.
@Hunter McMillen, sub { my $r = shift; $r &&= $r->{$_} for @_; $r } would be fine if you wanted to fetch from the structure, but since we're adding to the structure, we need to end up with a reference to the last value. You can do that by handling the last key specially, but the extra level of indirection makes things so much easier.
@Hunter McMillen, This does something similar, but uses aliases instead of references. Aliases using Data::Alias: sub DiveVal :lvalue { alias my $s = shift; alias $s = $s->{$_} for @_; $s }. Aliases using the refaliasing feature: sub DiveVal :lvalue { \my $s = \shift; \$s = \( $s->{$_} ) for @_; $s }.
@ikegami, Your soltion looks good but unfortunatly, that script must but run on a system on which I cannot install any additional modules and that module is not available on the target machine. I will try to find an other solution without creating the hash in that way
-1

you can do it this way, its not the most efficient but it works

use Data::Dumper;

my @array = ('a','b','c');
my $dataname = 'my data';
my $datavalue = '123';

my $hash = {$dataname => $datavalue};

foreach my $item (reverse @array){
    $hash = {$item =>$hash};
}
my %hash =%$hash;
print Dumper(\%hash);

you will get the following output:

$VAR1 = {
          'a' => {
                   'b' => {
                            'c' => {
                                     'my data' => '123'
                                   }
                          }
                 }
        };

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.