Autovivification within deep nested hash

Discussion in 'Perl Misc' started by niall.macpherson@ntlworld.com, May 12, 2006.

  1. Guest

    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::Dumper;

    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:www:xxx
    secondone:17878:555555:4444:ddd:ppp
    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
    , May 12, 2006
    #1
    1. Advertising

  2. Guest

    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
    , May 12, 2006
    #2
    1. Advertising

  3. Paul Lalli Guest

    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::Dumper;
    >
    > 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:www:xxx
    > secondone:17878:555555:4444:ddd:ppp
    > 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
    Paul Lalli, May 12, 2006
    #3
  4. Paul Lalli Guest

    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::Dumper;

    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:www:xxx
    secondone:17878:555555:4444:ddd:ppp
    thirdone:14545:66666:1111:qqq:lll
    thirdone:15656:7777:aaaaa:aaaaa:zzzz
    Paul Lalli, May 12, 2006
    #4
  5. 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;
    }
    Brian McCauley, May 12, 2006
    #5
  6. Uri Guttman Guest

    >>>>> "PL" == Paul Lalli <> 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 ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
    Uri Guttman, May 12, 2006
    #6
  7. Guest

    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.
    , May 15, 2006
    #7
  8. Brad Baxter Guest

    Brad Baxter, May 15, 2006
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. rp
    Replies:
    1
    Views:
    494
    red floyd
    Nov 10, 2011
  2. John Carter
    Replies:
    1
    Views:
    102
    gabriele renzi
    Dec 1, 2003
  3. Siratinee Sukachai
    Replies:
    1
    Views:
    137
    7stud --
    Apr 22, 2011
  4. sm
    Replies:
    1
    Views:
    71
    DJ Stunks
    Jan 4, 2007
  5. Frank Seitz

    Autovivification by foreach

    Frank Seitz, Mar 12, 2009, in forum: Perl Misc
    Replies:
    5
    Views:
    144
    Peter J. Holzer
    Mar 14, 2009
Loading...

Share This Page