Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Autovivification within deep nested hash

Reply
Thread Tools

Autovivification within deep nested hash

 
 
niall.macpherson@ntlworld.com
Guest
Posts: n/a
 
      05-12-2006
I have a very deep nested hash and I need to set a lot of values at one
of the lowest levels.
Eg if I wanted to do something like

$a{b}{c}{d}{e}{f}{'bit1} = 'val1';
$a{b}{c}{d}{e}{f}{'bit2} = 'val2';
......... etc etc
I'd like to be able to assign a variable (say $thisone) to the top
levels ($a{b}{c}{d}{e}{f}) so that I could do

$thisone->{'bit1} = 'val1';
$thisone->{'bit2} = 'val2';

Which would make it more readable.

I have partly achieved this - the following code works
------------------------------------------------------------------------------------------------------------------------------
use strict;
use warnings;
use Data:umper;

my %tableinfo;

while(<DATA>)
{
chomp;
my($table, $tstamp, $value, $morestuff, $yetmore, $evenmore) =
split(/:/);

$tableinfo{$table}{total} += $value;

## Want to make this line more readable
$tableinfo{$table}{stats}{$tstamp}{value} = $value; ## simplify this
line

my $thisone = $tableinfo{$table}{stats}{$tstamp}; ## assign
shortcut
## Can't do $thisone->{value} = $value . Autovivification ?
$thisone->{morestuff} = $morestuff;
$thisone->{yetmore} = $yetmore;
$thisone->{evenmore} = $evenmore;

$tableinfo{$table}{total} += $value;

}
print Dumper \%tableinfo;

__DATA__
firstone:12345:11111:9999:ccc:vvv
secondone:16767:22222:8888:bbb:nnn
firstone:12367:33333:7777:zzz:qqq
firstone:12389:44444:6666:wwwxx
secondone:17878:555555:4444:dddpp
thirdone:14545:66666:1111:qqq:lll
thirdone:15656:7777:aaaaa:aaaaa:zzzz
-------------------------------------------------------------------------------------------------------------------------------

However as you can see I have been unable to shorten the first
assignnment line (marked 'simplify this line').

I can't do the line marked 'assign shortcut' and then $thisone->{value}
= $value presumably because until $tableinfo{$table}{stats}{$tstamp}
has been autovivified in the first assignment it doesn't exist.

My real world structure has about 8 levels of nexting so I want to keep
it as readable as possible.

Any suggestions for the best way to do this ?

Thanks

 
Reply With Quote
 
 
 
 
xhoster@gmail.com
Guest
Posts: n/a
 
      05-12-2006
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> I have a very deep nested hash and I need to set a lot of values at one
> of the lowest levels.
> Eg if I wanted to do something like
>
> $a{b}{c}{d}{e}{f}{'bit1} = 'val1';
> $a{b}{c}{d}{e}{f}{'bit2} = 'val2';
> ........ etc etc
> I'd like to be able to assign a variable (say $thisone) to the top
> levels ($a{b}{c}{d}{e}{f}) so that I could do
>
> $thisone->{'bit1} = 'val1';
> $thisone->{'bit2} = 'val2';
>
> Which would make it more readable.


....

You need to make $thisone an alias rather than copy to the hash value.

## generate loop that does nothing but make $thisone an alias
foreach my $thisone ( $tableinfo{$table}{stats}{$tstamp}) {
$thisone->{value} = $value ; ## now can do this
> $thisone->{morestuff} = $morestuff;
> $thisone->{yetmore} = $yetmore;
> $thisone->{evenmore} = $evenmore;


};


Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
 
Reply With Quote
 
 
 
 
Paul Lalli
Guest
Posts: n/a
 
      05-12-2006
(E-Mail Removed) wrote:
> I have a very deep nested hash and I need to set a lot of values at one
> of the lowest levels.
> Eg if I wanted to do something like
>
> $a{b}{c}{d}{e}{f}{'bit1} = 'val1';
> $a{b}{c}{d}{e}{f}{'bit2} = 'val2';
> ........ etc etc
> I'd like to be able to assign a variable (say $thisone) to the top
> levels ($a{b}{c}{d}{e}{f}) so that I could do
>
> $thisone->{'bit1} = 'val1';
> $thisone->{'bit2} = 'val2';
>
> Which would make it more readable.
>
> I have partly achieved this - the following code works
> ------------------------------------------------------------------------------------------------------------------------------
> use strict;
> use warnings;
> use Data:umper;
>
> my %tableinfo;
>
> while(<DATA>)
> {
> chomp;
> my($table, $tstamp, $value, $morestuff, $yetmore, $evenmore) =
> split(/:/);
>
> $tableinfo{$table}{total} += $value;
>
> ## Want to make this line more readable
> $tableinfo{$table}{stats}{$tstamp}{value} = $value; ## simplify this
> line
>
> my $thisone = $tableinfo{$table}{stats}{$tstamp}; ## assign
> shortcut
> ## Can't do $thisone->{value} = $value . Autovivification ?
> $thisone->{morestuff} = $morestuff;
> $thisone->{yetmore} = $yetmore;
> $thisone->{evenmore} = $evenmore;
>
> $tableinfo{$table}{total} += $value;
>
> }
> print Dumper \%tableinfo;
>
> __DATA__
> firstone:12345:11111:9999:ccc:vvv
> secondone:16767:22222:8888:bbb:nnn
> firstone:12367:33333:7777:zzz:qqq
> firstone:12389:44444:6666:wwwxx
> secondone:17878:555555:4444:dddpp
> thirdone:14545:66666:1111:qqq:lll
> thirdone:15656:7777:aaaaa:aaaaa:zzzz
> -------------------------------------------------------------------------------------------------------------------------------
>
> However as you can see I have been unable to shorten the first
> assignnment line (marked 'simplify this line').
>
> I can't do the line marked 'assign shortcut' and then $thisone->{value}
> = $value presumably because until $tableinfo{$table}{stats}{$tstamp}
> has been autovivified in the first assignment it doesn't exist.


I believe that assesment is correct. Reading a multi-level structure
does not involve autovivification, assigning to it does.

> My real world structure has about 8 levels of nexting so I want to keep
> it as readable as possible.
>
> Any suggestions for the best way to do this ?


In your above case, you can do:
$tableinfo{$table}{stats}{$tstamp} = {};
rather than
$tableinfo{$table}{stats}{$tstamp}{value} = $value;
just to keep the symmetry of all the $thisone->{} statements intact,
but I don't know if that's still not readable enough for you.

Another suggestion might be to make %thisone an empty hash, then do
your deep assignments, and assign that back to the main structure
afterwords...

my %thisone = (value => $value, morestuff => $morestuff,
yetmore => $yetmore, evenmore=> $evenmore);
$tableinfo{$table}{stats}{$tstamp} = \%thisone;

Again the increased readability of that is debateable.

Paul Lalli

 
Reply With Quote
 
Paul Lalli
Guest
Posts: n/a
 
      05-12-2006
Jim Gibson wrote:

> You want to assign a reference to $thisone (untested):


Please consider testing in the future. Really wouldn't have taken that
long...

> my $thisone = \$tableinfo{$table}{stats}{$tstamp};


$thisone is now a reference to the undefined value.

> > ## Can't do $thisone->{value} = $value . Autovivification ?
> > $thisone->{morestuff} = $morestuff;
> > $thisone->{yetmore} = $yetmore;
> > $thisone->{evenmore} = $evenmore;

>
> Should work now.


No it shouldn't. Now you get:
Not a HASH reference at ./clpm.pl line 19, <DATA> line 1.

(Modified code pasted below for verification purposes)

Paul Lalli

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

my %tableinfo;

while(<DATA>){
chomp;
my($table, $tstamp, $value, $morestuff, $yetmore, $evenmore) =
split(/:/);

$tableinfo{$table}{total} += $value;

## Want to make this line more readable
# $tableinfo{$table}{stats}{$tstamp}{value} = $value; ## simplify
this line

## Can't do $thisone->{value} = $value . Autovivification ?
my $thisone = \$tableinfo{$table}{stats}{$tstamp};
$thisone->{value} = $value;
$thisone->{morestuff} = $morestuff;
$thisone->{yetmore} = $yetmore;
$thisone->{evenmore} = $evenmore;

$tableinfo{$table}{total} += $value;

}

print Dumper \%tableinfo;

__DATA__
firstone:12345:11111:9999:ccc:vvv
secondone:16767:22222:8888:bbb:nnn
firstone:12367:33333:7777:zzz:qqq
firstone:12389:44444:6666:wwwxx
secondone:17878:555555:4444:dddpp
thirdone:14545:66666:1111:qqq:lll
thirdone:15656:7777:aaaaa:aaaaa:zzzz

 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      05-12-2006

Tim Hammerquist wrote:

> my $thisone = ( $tableinfo{$table}{stats}{$tstamp} ||= {} );
> $thisone->{value} = $value;


There's nothing wrong with that idiom and it's the one I most often use
but you can also use some others (some of which have been mentioned
elsewhere in this thread already).

my $thisone = \$tableinfo{$table}{stats}{$tstamp};
$$thisone->{value} = $value;


my $thisone = \%{$tableinfo{$table}{stats}{$tstamp}};
$thisone->{value} = $value;


for my $thisone ( $tableinfo{$table}{stats}{$tstamp} ) {
$thisone->{value} = $value;
}

 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      05-12-2006
>>>>> "PL" == Paul Lalli <(E-Mail Removed)> writes:

>> I can't do the line marked 'assign shortcut' and then $thisone->{value}
>> = $value presumably because until $tableinfo{$table}{stats}{$tstamp}
>> has been autovivified in the first assignment it doesn't exist.


PL> I believe that assesment is correct. Reading a multi-level structure
PL> does not involve autovivification, assigning to it does.

you have it wrong there. if you read a deep but nonexisted slot (meaning
parent slots are missing) perl will autovivify all the parents. the
final slot itself doesn't get autovivified. and exists() doesn't handle
that as well.

OP: read my autovivification tutorial:

http://sysarch.com/Perl/autoviv.txt

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
 
Reply With Quote
 
niall.macpherson@ntlworld.com
Guest
Posts: n/a
 
      05-15-2006
Uri Guttman wrote:
>
> OP: read my autovivification tutorial:
>
> http://sysarch.com/Perl/autoviv.txt
>
> uri
>


Thanks to those who responded - all very useful advice. Having now read
Uri's autovivification tutorial I would thoroughly recommend it.

 
Reply With Quote
 
Brad Baxter
Guest
Posts: n/a
 
      05-15-2006
Uri Guttman wrote:
>
> OP: read my autovivification tutorial:
>
> http://sysarch.com/Perl/autoviv.txt


s/thay/they/;
s/refered/referred/;



--
Brad

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
Autovivification by foreach Frank Seitz Perl Misc 5 03-14-2009 11:36 AM
dealing with nested xml within nested xml within...... Ultrus Python 3 07-09-2007 09:00 PM
A difficulty with *surprising autovivification* in using %HASH sm Perl Misc 1 01-04-2007 07:02 PM
Rite, Block locals and Autovivification John Carter Ruby 1 12-01-2003 10:02 PM



Advertisments