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

Hi, I am using the following code block to produce the datastructure shown as output.
open (NEW , "< /text.txt"); while(<NEW>){ @val=split /\t/; $Tech_fy_reldata{$val[$npo]}{$val[$fy_closed]}[0] = '0'; } ________OUTPUT_______ $VAR5 = 'Data'; $VAR6 = { '2007' => [ '0' ] }; $VAR7 = 'DataBase'; $VAR8 = { '2005' => [ '0' ], '' => [ '0' ], '2007' => [ '0' ], '2004' => [ '0' ], '2006' => [ '0' ] };
My requirment is instead of using a predefined HoH ($Tech_fy_reldata{$val[$npo]}{$val[$fy_closed]}[0] = '0';) , I need to create the same kind of output for more no of key is more levels of hash dynamicaly.

For ex, instead of $npo,$fy_closed there may be any variables and more than two or even one.
Values $npo,$fy_closed are stored in an array.So based upon the no of elements in the array my hash tobe builded.

Basically i am using this structure to group the line in a text file(somthing like group by clause in sql)

Is there any otherway to accomplish this task? Please help me. Thanks

Replies are listed 'Best First'.
Re: Generating HoH...
by liverpole (Monsignor) on Dec 10, 2006 at 13:58 UTC
    One idea comes immediately to mind, and that's to use references.

    A reference is basically a pointer; you use it to point to the data you're working with, and then dereference it to assign or read its current value.

    So, for example, with phash being the reference (pointer) to your hash:

    my $phash = \%Tech_fy_reldata; # Assign to hash reference (eg. \%hash +) while(<NEW>){ @val=split /\t/; foreach my $val (@val) { my $pvalue = $phash; # Start with reference to hash if (CONDITION1) { $pvalue = $pvalue->{KEY1}; # Down 1 level if (CONDITION2) { $pvalue = $pvalue->{KEY2}; # Down another level # ... etc ... } } $$pvalue = VALUE; # Use $$ to dereference for assignment } }
    In the above code, CONDITION1, CONDITION2, etc. are the conditions you've chosen to descend another level in the hash, and KEY1, KEY2, etc. are the corresponding keys at each lower level.  So, in your original example, if the keys were $val[$npo] and $val[$fy_closed], then when you got to the line:
    $$pvalue = VALUE; # Use $$ to dereference for assignment

    $pvalue would be pointing to $Tech_fy_reldata{$val[$npo]}{$val[$fy_closed]}, and the assignment is made by dereferencing the pointer with $$pvalue.  Each time through the loop, the pointer pvalue gets reinitialized to the top-level hash pointer.

    Try reading perlref and/or perlreftut if you'd like more information on references.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: Generating HoH...
by johngg (Canon) on Dec 10, 2006 at 13:01 UTC
    It is difficult to divine your requirements without an example of the data you are working with. Would it be possible for you to post a sample (sanitized if necessary) of the data so that we have a better chance of helping you.

    In your code snippet, where does $npo get initialised, ditto $fy_closed? Also, looking at your output, there is an empty key in the $VAR8 hash which suggests that there might be multiple TAB delimiters or missing data fields.

    Please give us some more to go on.

    Cheers

    JohnGG

Re: Generating HoH... (dive)
by tye (Sage) on Dec 10, 2006 at 18:43 UTC

    See Data::Diver:

    use Data::Diver qw( DiveVal ); # ... while( <...> ) { @val= split /\t/; DiveVal( \%Tech_fy_r­eldata, \( @val ) )= '0'; }

    Might be close to what you wanted (hard to say for sure since you don't show what $npo and $fy_closed are defined as).

    - tye        

Re: Generating HoH...
by ikegami (Patriarch) on Dec 11, 2006 at 02:19 UTC
    You seem to be ignoring our advice. Why do you come back? Sorry if those weren't posted by you, but the resemblence is uncanny.