Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Undesirable parent hash keys

by sophate (Beadle)
on Jan 11, 2013 at 07:33 UTC ( [id://1012812]=perlquestion: print w/replies, xml ) Need Help??

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

Dear monks,

I would like to describe my problem with some sample codes below.

my %Hash; $Hash{'2012'}{'Jan'}{'13th'} = 1; # set 13th Jan 2012 to true $Hash{'2012'}{'Feb'}{'10th'} = 1; # set 10th Feb 2012 to true if ($Hash{'2013'}{'Oct'}{'11th'}{'1AM'}{'30Min'}) { # if so, do something } ## The if statement sets $Hash{'2013'}{'Oct'}{'11th'} to a hash ref ## which is undesirable. ## What I want is not to create $Hash{'2013'} at all. ## Later on if I check if ($Hash{'2013'}{'Oct'}{'11th'}) { ## I will end up here . . . ## I only want to be here if I set ## $Hash{'2013'}{'Oct'}{'11th'} = 1 explicitly. }

The problem is with the 'if ($Hash{'2013'}{'Oct'}{'11th'}{'1AM'}{'30Min'})' statement which creates $Hash{'2013'}{'Oct'}{'11th'}{'1AM'} as a hash ref. Is there any way to check the existence of a nested hash key without creating the parent hash keys? I can change the if statement to the one below but it looks clumsy . . .

if ($Hash{'2013'} && $Hash{'2013'}{'Oct'} && $Hash{'2013'}{'Oct'}{'11t +h'} && $Hash{'2013'}{'Oct'}{'11th'}{'1AM'} && $Hash{'2013'}{'Oct'}{'1 +1th'}{'1AM'}{'30Min'}) { # do something here }

Replies are listed 'Best First'.
Re: Undesirable parent hash keys
by davido (Cardinal) on Jan 11, 2013 at 07:58 UTC

    See autovivification, a pragma (available from CPAN) that can lexically disable autovivification (the behavior). Here's an example from perlfaq4:

    { no autovivification; my %hash; if( exists $hash{key1}{key2}{key3} ) { ...; } }

    The faq also suggests a few other techniques.


    Dave

      thanks for the suggestion. but i'm planning to write my own function to check if a hash key exists without autovivification :-)

Re: Undesirable parent hash keys
by Athanasius (Archbishop) on Jan 11, 2013 at 07:50 UTC

    You should be testing using exists, because the boolean test you are using will return false if the hash element exists but is undef or zero or the empty string...

    That said, I don’t think there is any way to do what you want without the clumsy cascade of tests:

    if (exists $Hash{'2013'} && exists $Hash{'2013'}{'Oct'} && ...

    because exists also autovivifies intervening elements. According to the documentation:

    This surprising autovivification in what does not at first—or even second—glance appear to be an lvalue context may be fixed in a future release.

    :-(

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Noted and thanks for your prompt response.

Re: Undesirable parent hash keys (concept?)
by LanX (Saint) on Jan 11, 2013 at 08:43 UTC
    Do you really have an autovivification problem?

    > I only want to be here if I set $Hash{'2013'}{'Oct'}{'11th'} = 1 explicitly.

    If you only check  if ($Hash{'2013'}{'Oct'}{'11th'} == 1) { .. } you can't be bothered by hash-refs.

    Anyway better rethink your concept!

    When setting $Hash{'2013'}{'Oct'}{'11th'} = 1 you are overwriting a potential hashref to a nested hash and any previous $Hash{'2013'}{'Oct'}{'11th'}{'1AM'}{'30Min'}=1 will be lost.

    Better use an additional level of keys to mark and write and test $Hash{'2013'}{'Oct'}{'11th'}{MARK} or so.

    Cheers Rolf

      sorry for the confusion. the examaple i gave wasn't perfect. what i wanted to say is

      ## I only want to be here if I set ## $Hash{'2013'}{'Oct'}{'11th'} ## or $Hash{'2013'}{'Oct'}{'11th'}{...}...{...} ## explicitly.
        Then the only practical solution is to switch off autovivification. But take care to do it only in a limited scope because many other modules may still need it and could break unexpectedly if it is switched off.;

        It is probably more safe to do a no autovivification 'exists'; as this turns off autovivification for dereferencing expressions that are parts of an exists only, such as :

        exists $arrayref->[1][2][$idx] exists $hashref->{this}{that}{$key};
        and then make sure you change your tests to include the exists function.

        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

        My blog: Imperial Deltronics
Re: Undesirable parent hash keys
by Anonymous Monk on Jan 11, 2013 at 08:10 UTC
Re: Undesirable parent hash keys
by Anonymous Monk on Jan 11, 2013 at 17:26 UTC
    Also, unless at some future point you need to walk through and find only entries under a particular nested hash-key, you might consider creating a single string that consists of each of the parts, separated (say) by a vertical-bar character, e.g. 2013|Oct|11th|1AM, or some other useful-to-you variation on that theme.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1012812]
Approved by Athanasius
Front-paged by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-03-19 09:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found