Joooooom
Joooooom

Reputation: 113

Array content into hash KEYS in a row

I have a problem that I solved but in a dirty and non-dynamic way. So i'd like to know if anybody had a better solution.

I have an array, and I want to use each element of an array as keys for a SINGLE value (I don't care about the value actually, I use this method to build a sort of tree, but anyway, that's not the point)

My solution is like this atm :

@array = qw(un deux voila coucou hey whatsup);

$num_elements = scalar(@array);

switch ($num_elements) {
    case 1  { $arbre{$array[0]} = 1 }
    case 2  { $arbre{$array[0]}{$array[1]} = 2 }
    case 3  { $arbre{$array[0]}{$array[1]}{$array[2]} = 3 }
    case 4  { $arbre{$array[0]}{$array[1]}{$array[2]}{$array[3]} = 4 }
    case 5  { $arbre{$array[0]}{$array[1]}{$array[2]}{$array[3]}{$array[4]} = 5 }
    case 6  { $arbre{$array[0]}{$array[1]}{$array[2]}{$array[3]}{$array[4]}{$array[5]} = 6 }
    case 7  { $arbre{$array[0]}{$array[1]}{$array[2]}{$array[3]}{$array[4]}{$array[5]}{$array[6]} = 7 }
    else { print "previous case not true" }
}

As you can see it only works if I have no more than 7 elements in my array, otherwise I'll have to add another case. And of course it might happen since I'll do this with several arrays.

Anybody has a better solution ? Condisering the fact that I really dont care about the value. I put 1 2 3 4... 7 as ans exemple but it could be 1 or 5 anywhere it wouldn't matter.

Thanks !

Upvotes: 0

Views: 107

Answers (2)

ikegami
ikegami

Reputation: 385789

Use Data::Diver.

use Data::Diver qw( DiveVal );

my %arbre;
DiveVal(\%arbre, map \$_, @array) = 1;

Without Data::Diver:

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

my %arbre;
dive(\%arbre, @array) = 1;

Depending on how you use the hash, you might be able to use the following solution which is much simpler and uses far less memory:

# If you can guarantee that chr(0) won't occur in @array
$arbre{ join "\0", @array } = 1;

# If @array can contain any characters. (5.10+, IIRC)
$arbre{ pack('(N/a*)*', @array } = 1;

PS - I recommend against using the Switch.pm module. It's an experimental module that can result in really hard to diagnose errors, and it doesn't really help you at all.

Upvotes: 1

Borodin
Borodin

Reputation: 126722

If the final value doesn't matter then presumably another hash reference will do?

Like this

use strict;
use warnings;

my @keys = qw(un deux voila coucou hey whatsup);
my %arbre;

my $hash = \%arbre;
$hash = ( $hash->{$_} = {} ) for @keys;

use Data::Dump;
dd \%arbre;

output

{
  un => { deux => { voila => { coucou => { hey => { whatsup => {} } } } } },
}

Upvotes: 4

Related Questions