Search code examples
perlhash-of-hashes

Access nested hash in Perl HoH without using keys()?


Consider the following HoH:

$h = {
    a => {
           1 => x
    },
    b => {
           2 => y
    },
    ...
}

Is there a way to check whether a hash key exists on the second nested level without calling keys(%$h)? For example, I want to say something like:

if ( exists($h->{*}->{1}) ) { ...

(I realize you can't use * as a hash key wildcard, but you get the idea...)

I'm trying to avoid using keys() because it will reset the hash iterator and I am iterating over $h in a loop using:

while ( (my ($key, $value) = each %$h) ) {
    ...
}

The closest language construct I could find is the smart match operator (~~) mentioned here (and no mention in the perlref perldoc), but even if ~~ was available in the version of Perl I'm constrained to using (5.8.4), from what I can tell it wouldn't work in this case.

If it can't be done I suppose I'll copy the keys into an array or hash before entering my while loop (which is how I started), but I was hoping to avoid the overhead.


Solution

  • No. each uses the hash's iterator, and you cannot iterate over a hash without using its iterator, not even in the C API. (That means smart match wouldn't help anyway.)

    Since each hash has its own iterator, you must be calling keys on the same hash that you are already iterating over using each to run into this problem. Since you have no problem calling keys on that hash, could you just simply use keys instead of each? Or maybe call keys once, store the result, then iterate over the stored keys?