forgedascendant has asked for the wisdom of the Perl Monks concerning the following question:

Hello everyone, What I am trying to do is create a hash to test some code I wrote. The problem is I have little experiance with hashes so I went on line and searched the web and put together my best guess. The Hash call I need to meet is as follows:
@idlarge = ($Data_Hash{$Call_Hash{"TST_" . "IDS_Large_1"}}, $Data_Hash +{$Call_Hash{"TST_" . "IDS_Large_2"}}, ... @idsmall = ($Data_Hash{$Call_Hash{"TST_" . "IDS_Small_1"}}, $Data_Hash +{$Call_Hash{"TST_" . "IDS_Small_2"}}, ... @Vg = ($Call_Hash{"OPT_" . "VGS_1"}, $Call_Hash{"OPT_" . "VGS_2"}, ...
What I am doing is creating the hash to these calls. After searching online I put it all together and came up with the following:
%Data_Hash = ( %Call_Hash = ( TST_IDS_Large_1 =>2.9E-12, TST_IDS_Large_2 =>1.85E-12, TST_IDS_Small_1 =>1.86E-9, TST_IDS_Small_2 =>2.83E-9, ), OPT_VGS_1 =>0, OPT_VGS_2 =>0.02, );
From trying to call the hash I can tell you that what I have is not correct. I can get the information in the first level of the hash but nothing beneith it. Can someone please tell me where I have gone wrong in creating the hash? Aaron

Replies are listed 'Best First'.
Re: Hash Within A Hash
by kennethk (Abbot) on May 19, 2009 at 21:23 UTC
    The article you'll want to read is perllol. The primary issue you are having is that multi-level data structures are formed using the flat data structures combined with references to other data structures - Perl just does it explicitly. The syntax you want in order to create your hash is probably:

    %Data_Hash = ( Call_Hash => { TST_IDS_Large_1 =>2.9E-12, TST_IDS_Large_2 =>1.85E-12, TST_IDS_Small_1 =>1.86E-9, TST_IDS_Small_2 =>2.83E-9, }, OPT_VGS_1 =>0, OPT_VGS_2 =>0.02, );

    {key1 => val1, key2 => val2} returns a scalar pointer to a hash with the key value pairs listed. In order to interact with it, your code would read:

    @idlarge = ($Data_Hash{Call_Hash}{"TST_" . "IDS_Large_1"}, $Data_Hash{Call_Hash}{"TST_" . "IDS_Large_2"}, ...)

    or

    @idlarge = ($Data_Hash{Call_Hash}->{"TST_" . "IDS_Large_1"}, $Data_Hash{Call_Hash}{"TST_" . "IDS_Large_2"}, ...)

    since consecutive indices contain an implicit deference.

    Update: I misunderstood the spec. Assuming that your access methods are correct, you actually want two completely separate hashes. The values of %Call_Hash are being used as keys in the %Data_Hash. The data structures you want are given by:

    %Data_Hash = ( OPT_VGS_1 =>0, OPT_VGS_2 =>0.02, ); %Call_Hash = ( TST_IDS_Large_1 =>2.9E-12, TST_IDS_Large_2 =>1.85E-12, TST_IDS_Small_1 =>1.86E-9, TST_IDS_Small_2 =>2.83E-9, );

    except that the values of %Call_Hash should correspond to keys in %Data_Hash.

Re: Hash Within A Hash
by grantm (Parson) on May 19, 2009 at 21:21 UTC

    A good place to start is the perlreftut documentation - a tutorial on Perl references.

Re: Hash Within A Hash
by CountZero (Bishop) on May 19, 2009 at 21:25 UTC
    %Data_Hash = ( 'Call_Hash' => { TST_IDS_Large_1 =>2.9E-12, TST_IDS_Large_2 =>1.85E-12, TST_IDS_Small_1 =>1.86E-9, TST_IDS_Small_2 =>2.83E-9, }, 'OPT_VGS_1' => 0, 'OPT_VGS_2' => 0.02, );

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Hash Within A Hash
by GrandFather (Saint) on May 20, 2009 at 01:50 UTC

    There are a couple of things that will help with this sort of problem:

    Always use strictures (use strict; use warnings;). They give an early warning about things going pear shaped and often provide the right information to figure out what the nature of the problem is.

    Data::Dump::Streamer or Data::Dumper provide really useful ways of visualizing complicated data structures.

    Of course reading the documentation that others have suggested will help a great deal too. Managing interesting data structures is at least as important to attaining Perl proficiency as knowing how to use Perl's regular expressions.


    True laziness is hard work
Re: Hash Within A Hash
by LanX (Saint) on May 19, 2009 at 21:36 UTC
    You should have a look at HASHES OF HASHES!

    The essential difficulty in perl is, you can represent the same datastructure in a reference form (eg \%Hash) and in (what I call) a list form (eg %Hash). For nesting you need references, because lists are flattened:

    (1,(2,3)) is nothing else then (1,2,3)

    but (1,[2,3]) is a list with a literal reference to an array as second element.

    As mentioned above better also have a look into perlreftut

    Cheers Rolf

Re: Hash Within A Hash
by forgedascendant (Novice) on May 19, 2009 at 21:33 UTC
    Unfortunatly, I have no control over the call. What I have to do is build the original Hash from the call. I went and tried what Zero suggested and it still doesn't want to give the value up.
      What do you mean with I have no control over the call.?

      You are not "calling" anything in your code.

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Hash Within A Hash
by Anonymous Monk on May 20, 2009 at 04:26 UTC
    $Data_Hash{$Call_Hash{"TST_" . "IDS_Large_1"}}, ...

    It seems you have two 1-D hashes rather than one 2-D hash. "TST_" . "IDS_Large_1" is a key to %Call_Hash
    $Call_Hash{"TST_" . "IDS_Large_1"} is the value corresponding to that key. You are using that value from %Call_Hash as a key for %Data_Hash. So try something like:
    %Call_Hash = ( TST_IDS_Large_1 =>"OPT_VGS_1", TST_IDS_Large_2 =>"OPT_VGS_2", TST_IDS_Small_1 =>"OPT_VGS_3", TST_IDS_Small_2 =>"OPT_VGS_4" ); %Data_Hash = ( OPT_VGS_1 =>0, OPT_VGS_2 =>0.02, OPT_VGS_3 =>0.04, OPT_VGS_4 =>0.08 );
    The values of %Call_Hash will need to be keys of %Data_Hash (at least the ones you want to use for keys)