hal9e3
hal9e3

Reputation: 9

Create Multi Dimensional Hash Using Array Elements

I need to create multidimensional hashes with varying depth using array elements as keys. Pseudocode attempt:

Example line:

Statement Coverage for instance Hierarchical/path/with/block/and/module ...

if (/Statement Coverage for instance (.&?) /)
{
@array = split /\//, $1;
}

for (my $eye = 1; $eye <= $#array; $eye++)
{
A miracle happens to %hash!
}

$hash{"path"}{"with"}{"block"}{"and"} now has a value of "module". Remember, the number of keys can vary. Any ideas?

Upvotes: 0

Views: 230

Answers (2)

jira
jira

Reputation: 3944

See my code below. It builds the desired hash recursively.

But I think that you are taking a wrong approach. I obviously don't know what exactly you are trying to achieve, but seems to me, that you should use tree data structure instead of the multidimensional hash.

use strict;
use warnings;

use v5.10;


use Data::Dumper;

my @data = (
  'some/path/test',
  'some/path/deeper/test',
  'another/deeper/path/test',
);

my $resultHr = {};

foreach my $path (@data) {
  my @elems = split /\//, $path;
  buildHash($resultHr, @elems);
}

say Dumper($resultHr);


sub buildValue {
  my $n = shift;

  if (@_) {
    return {$n => buildValue(@_)};
  }
  else {
    return $n;
  }
}

sub buildHash {
  my $hr = shift;
  my $k = shift;

  return unless $k;

  if (exists $hr->{$k} && ref $hr->{$k}) {
    buildHash($hr->{$k}, @_);
  }
  else {
    $hr->{$k} = buildValue(@_);
  }
}

Upvotes: 1

choroba
choroba

Reputation: 242218

That's what Data::Diver does for you:

my @array = split /\//, $1;
DiveVal(\ my %hash, @array[ 0 .. $#array - 1 ]) = $array[-1];
print Dumper(\%hash);

Upvotes: 2

Related Questions