help: multi-dimensional hash from flat array 
Author Message
 help: multi-dimensional hash from flat array

i need to create an arbitrary multi-dimensional hash
from a flat array. i don't understand why the simple
$h{a}{b}{c}{d}{e}='x' ain't working.

thanks
--tako
====================================================

use strict;

## starting point:
##      string contains flattened representation of variable
##       could be arbitrarly deep , # of -'s
my $var = "a-b-c-d-e";

my %h =();


## creates the hash syntax from the names in array

my $m="";

         $m .="{$_}";

Quote:
}

## let eval do the assignment
my $r="%h->$m=823";

eval {$r};

my $q=%h->{a}{b}{c}{d}{e};

## should come back as 823 but it aint even there
print $q;



Sun, 15 May 2005 09:06:01 GMT  
 help: multi-dimensional hash from flat array

Quote:

> i need to create an arbitrary multi-dimensional hash
> from a flat array. i don't understand why the simple
> $h{a}{b}{c}{d}{e}='x' ain't working.

What you're doing below is {*filter*}ugly and very evil. If you're doing it
for educational purposes then read on.

Quote:
> use strict;

> ## starting point:
> ## string contains flattened representation of variable
> ##          could be arbitrarly deep , # of -'s
> my $var = "a-b-c-d-e";

> my %h =();




Quote:
> ## creates the hash syntax from the names in array

> my $m="";

>          $m .="{$_}";
> }

> ## let eval do the assignment
> my $r="%h->$m=823";

my $r = '$h' . "$m=823";

Quote:
> eval {$r};

eval $r;

Quote:

> my $q=%h->{a}{b}{c}{d}{e};

my $q=$h{a}{b}{c}{d}{e};

Quote:
> ## should come back as 823 but it aint even there
> print $q;

Cheers,
Bernard
--
echo 42|perl -pe '$#="Just another Perl hacker,"'


Sun, 15 May 2005 09:50:28 GMT  
 help: multi-dimensional hash from flat array
evil yes; but necessary. i found myself in a hole where
i need to create flat variable names (through a cgi- web page form) and
need to get it uniquely back into my session hash.

i have aribitrary widgets and associated error correction modules
for the widgets. i just ran into the case where i needed multiple blocks
of the same widgets on the same page. the different being each block of
widgets has a uid.
so to keep all my existing orthognal modules, i just added a function
call to each variable read/write with this {*filter*}ugly mapping.

What do you percieve and suggest as an elegant solution?

--tako
btw, thanks for the elgance of $r ='$h' . "$m=823";

i had forgotten that sometimes it's easier to split a string into small
pieces that to expand it in one shot.

Quote:


>>i need to create an arbitrary multi-dimensional hash
>>from a flat array. i don't understand why the simple
>>$h{a}{b}{c}{d}{e}='x' ain't working.

> What you're doing below is {*filter*}ugly and very evil. If you're doing it
> for educational purposes then read on.

>>use strict;

>>## starting point:
>>##      string contains flattened representation of variable
>>##       could be arbitrarly deep , # of -'s
>>my $var = "a-b-c-d-e";

>>my %h =();



>>## creates the hash syntax from the names in array

>>my $m="";

>>         $m .="{$_}";
>>}

>>## let eval do the assignment
>>my $r="%h->$m=823";

> my $r = '$h' . "$m=823";

>>eval {$r};

> eval $r;


>>my $q=%h->{a}{b}{c}{d}{e};

> my $q=$h{a}{b}{c}{d}{e};

>>## should come back as 823 but it aint even there
>>print $q;

> Cheers,
> Bernard
> --
> echo 42|perl -pe '$#="Just another Perl hacker,"'



Sun, 15 May 2005 10:10:38 GMT  
 help: multi-dimensional hash from flat array

Quote:

> i need to create an arbitrary multi-dimensional hash
> from a flat array. i don't understand why the simple
> $h{a}{b}{c}{d}{e}='x' ain't working.
> use strict;
use Data::Dumper;
> my $var = "a-b-c-d-e";
> my %h =();


my $ref=\\%h;                  

 $$ref->{$key}={};
 $ref = \$$ref->{$key};

Quote:
}
> ## let eval do the assignment
> my $r="%h->$m=823";

$$ref = 823;
print Dumper \%h;

hth, tina
--
http://www.tinita.de/        \  enter__| |__the___ _ _ ___
http://Movies.tinita.de/      \     / _` / _ \/ _ \ '_(_-< of
http://PerlQuotes.tinita.de/   \    \ _,_\ __/\ __/_| /__/ perception



Sun, 15 May 2005 13:59:55 GMT  
 help: multi-dimensional hash from flat array

Quote:


>> i need to create an arbitrary multi-dimensional hash
>> from a flat array. i don't understand why the simple
>> $h{a}{b}{c}{d}{e}='x' ain't working.

>  $$ref->{$key}={};

this line isn't necessary at all, so:


 $ref = \$$ref->{$key};

Quote:
}

--
http://www.tinita.de/        \  enter__| |__the___ _ _ ___
http://Movies.tinita.de/      \     / _` / _ \/ _ \ '_(_-< of
http://PerlQuotes.tinita.de/   \    \ _,_\ __/\ __/_| /__/ perception


Sun, 15 May 2005 14:05:54 GMT  
 help: multi-dimensional hash from flat array
On Wed, 27 Nov 2002 04:10:38 -0500, Chef Tako said:

Quote:
>evil yes; but necessary. i found myself in a hole where
>i need to create flat variable names (through a cgi- web page form) and
>need to get it uniquely back into my session hash.
>...
>What do you percieve and suggest as an elegant solution?

I think this works in more cases than the other response in this
thread, which doesn't respect existing values. Naive maybe, but
no modules came to my mind and this was a good exercise.

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my %h = ();
while ( my $line = <DATA> ) {
   chomp $line;
   my ($keys, $path) = split /=/, $line;
   $path = { $_ => $path } for reverse split /-/, $keys;
   merge( \%h, %$path );

Quote:
}

sub merge {

   merge ( $h->{$key}, %$val ), return if exists $h->{$key};
   $h->{ $key } = $val;

Quote:
}

print Dumper( \%h );

__DATA__
a-b-c-d-e=test1
f-g-h-i-j=test2
a-g-h-i-j=test3
a-b-h-i-j=test4
f-g-c-d-e=test5
__END__

There you go -- you too can avoid that {*filter*} old string eval.
Probably needs some error checking and such. Maybe some guru
will delurk and show us a way that avoids the separate loop
and recursion :-).

HTH

--damian



Mon, 16 May 2005 05:22:37 GMT  
 help: multi-dimensional hash from flat array

Quote:

> On Wed, 27 Nov 2002 04:10:38 -0500, Chef Tako said:
>>evil yes; but necessary. i found myself in a hole where
>>i need to create flat variable names (through a cgi- web page form) and
>>need to get it uniquely back into my session hash.
>>...
>>What do you percieve and suggest as an elegant solution?
> I think this works in more cases than the other response in this
> thread, which doesn't respect existing values.

it does... maybe you haven't read my second posting.

reagards, tina
--
http://www.tinita.de/        \  enter__| |__the___ _ _ ___
http://Movies.tinita.de/      \     / _` / _ \/ _ \ '_(_-< of
http://PerlQuotes.tinita.de/   \    \ _,_\ __/\ __/_| /__/ perception



Mon, 16 May 2005 12:34:51 GMT  
 help: multi-dimensional hash from flat array
On 28 Nov 2002 11:34:51 GMT, Tina Mueller said:

Quote:

>> On Wed, 27 Nov 2002 04:10:38 -0500, Chef Tako said:
>>>evil yes; but necessary. i found myself in a hole where
>>>i need to create flat variable names (through a cgi- web page form) and
>>>need to get it uniquely back into my session hash.
>>>...
>>>What do you percieve and suggest as an elegant solution?

>> I think this works in more cases than the other response in this
>> thread, which doesn't respect existing values.

>it does... maybe you haven't read my second posting.

Ah, so it does. I had seen your second post, but clearly hadn't
understood the reason for removing that line. My apologies.

<grover>Oh I am so embarrassed</grover>

--damian



Tue, 17 May 2005 00:12:04 GMT  
 help: multi-dimensional hash from flat array

Quote:

> i need to create an arbitrary multi-dimensional hash
> from a flat array. i don't understand why the simple
> $h{a}{b}{c}{d}{e}='x' ain't working.

[snip]
> ## starting point:
> ##      string contains flattened representation of variable
> ##       could be arbitrarly deep , # of -'s
> my $var = "a-b-c-d-e";
[snip]
> my $q=%h->{a}{b}{c}{d}{e};

> ## should come back as 823 but it aint even there

Try this:

   my %h;

   my $var = "a-b-c-d-e";

   my $href = \%h;



      $href = ( $href->{$_} ||= {} );
   }
   $href->{$finalkey} = 823;

   print $h{a}{b}{c}{d}{e}, "\n";

This solution is slightly less elegant than Tina Mueller's solution, but
there's only one level of references...

--
my $n = 2; print +(split //, 'e,4c3H r ktulrnsJ2tPaeh'
."\n1oa! er")[map $n = ($n * 24 + 30) % 31, (42) x 26]



Thu, 19 May 2005 05:09:10 GMT  
 help: multi-dimensional hash from flat array
Just for completeness then here's the compact version without any loops:

my $var = "a-b-c-d-e";
my %h;
(my $statement = qq[\$h{$var}=823]) =~ s/-/}{/g;
eval $statement;

print $h{a}{b}{c}{d}{e};

*or* Damian's solution hacked a bit for those who like it hot:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my %h;

my $statements = join ("", <DATA>);
$statements =~ s/^(.+)$/\$h\{$1;/gm;
$statements =~ s/-/\}\{/gm;
$statements =~ s/(\{[^=]+)=/$1\}=/gm;
eval $statements; # five assignments with 1x eval

print Dumper( \%h );
exit;

__DATA__
a-b-c-d-e="test1"
f-g-h-i-j="test2"
a-g-h-i-j="test3"
a-b-h-i-j="test4"
f-g-c-d-e="test5"

Greetings, Simon

Quote:

> i need to create an arbitrary multi-dimensional hash
> from a flat array. i don't understand why the simple
> $h{a}{b}{c}{d}{e}='x' ain't working.

[snip]


Mon, 23 May 2005 12:39:24 GMT  
 help: multi-dimensional hash from flat array

Quote:

> Just for completeness then here's the compact version without any
> loops:

> my $var = "a-b-c-d-e";
> my %h;
> (my $statement = qq[\$h{$var}=823]) =~ s/-/}{/g;

The /g on your s/// performs a loop.

Quote:
> eval $statement;

Out of curiousity, what happens if someone has a string like:

   'a-b-system "rm /*"-c-d'

Quote:

> print $h{a}{b}{c}{d}{e};

--
my $n = 2; print +(split //, 'e,4c3H r ktulrnsJ2tPaeh'
."\n1oa! er")[map $n = ($n * 24 + 30) % 31, (42) x 26]


Mon, 23 May 2005 22:58:10 GMT  
 help: multi-dimensional hash from flat array

Quote:


> > Just for completeness then here's the compact version without any
> > loops:

> > my $var = "a-b-c-d-e";
> > my %h;
> > (my $statement = qq[\$h{$var}=823]) =~ s/-/}{/g;

> The /g on your s/// performs a loop.

Correct. But this "implicit" loop works much faster at run-time than
the equivalent "explicit" loop. However in the example code then any
run-time speed advantage gained in this way is lost by the very slow
eval statement. In all then the solution I suggested works about 3
times slower than your solution. On the plus side then it might be
considered easier to debug and/or maintain for non-Perl-Gurus (please
see snipprt of run-time generated code below). What do you think?

Having said all this then I normally go for recursive solutions
specifically for the performance reasons. However in this thread then
Damian already made that offering...

Quote:
> > eval $statement;

> Out of curiousity, what happens if someone has a string like:

>    'a-b-system "rm /*"-c-d'

This is an excellent example of how something dangerous can occur--and
a good reason why one should not conduct everyday business logged in
as "root" :-)

What we really want is run-time generated code looking like this in
order to avoid danger:

$h{'a'}{'b'}{'system "rm /*"'}{'c'}{'d'}="test0";
$h{'a'}{'b'}{'c'}{'d'}{'e'}="test1";
$h{'f'}{'g'}{'h'}{'i'}{'j'}="test2";
$h{'a'}{'g'}{'h'}{'i'}{'j'}="test3";
$h{'a'}{'b'}{'h'}{'i'}{'j'}="test4";
$h{'f'}{'g'}{'c'}{'d'}{'e'}="test5";

Produced from:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my %h;

my $statements = join ("", <DATA>);
$statements =~ s/^(.+)$/\$h\{'$1;/gm;
$statements =~ s/-/'\}\{'/gm;
$statements =~ s/(\{[^=]+)=/$1'\}=/gm;
eval $statements;

print Dumper( \%h );
exit;

__DATA__
a-b-system "rm /*"-c-d="test0"
a-b-c-d-e="test1"
f-g-h-i-j="test2"
a-g-h-i-j="test3"
a-b-h-i-j="test4"
f-g-c-d-e="test5"

Such a danger could pop-up anywhere if one doesn't beware:

my %h;

my $var = 'a-b-system "rm /*"-c-d';

my $href = \%h;



  $href = ( $href->{$_} ||= {} );

Quote:
}

$href->{$finalkey} = 823;

# print $h{a}{b}{system "rm /*"}{c}{d}, "\n";
#                ^^^ Danger, Will Robinson!

print $h{'a'}{'b'}{'system "rm /*"'}{'c'}{'d'}, "\n";

Greetings, Simon



Tue, 24 May 2005 11:55:42 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. multi-dimensional arrays with hashes help please

2. Incrementing a Multi-dimensional Hash Array

3. Help with multi-dimensional array

4. multi-dimensional arrays - more help please!

5. Help understanding Lists of Lists or Multi-dimensional arrays

6. Help: Multi-dimensional arrays & such

7. Help with Multi-dimensional array

8. Need help with multi-dimensional arrays was:tie

9. Weird Hash w/ n-dimensional two-dimensional array !!!!!!

10. arrays, multi-dimensional arrays, pointers and such

11. Associative arrays and multi-dimensional arrays.

12. Multi-Dimensional arrays, DBMs, and Assoc. Arrays

 

 
Powered by phpBB® Forum Software