in reply to Re: Test if a subhash in a referenced hash exists
in thread Test if a subhash in a referenced hash exists

Have a look at the very useful References quick reference.

Also, the keys doc. The argument for keys must be a hash and has a % sigil.

for my $key (keys %hash){ #... } for my $key (keys %{$hashref}){ # dereferencing a hash #... }
The exists doc tells you its argument is a hash element which will have a $ sigil. You need to read your error message
exists argument is not a HASH or ARRAY element
as
exists argument is neither a HASH element nor an ARRAY element
if (exists $hash{some_key}){ #.. } if (exists $hashref->{some_key}){ # dereferencing a hash element using + an arrow #.. }
An observation.
...what about %{$$coordinates{$group}{$id}{$stage}{"coords"}}...
The %{...} does the dereferencing, there's no need for the extra $ in $$. I prefer the -> for dereferencing (many monks don't) but it is often unnecessary (as in this case).

Have a look at the tutorial linked to above. I look at it at least once a week. :-)

update: When I'm have a fight with a convoluted data structure I try out the syntax on a simplified version and get that working first. And while you're doing that don't forget the mighty Data::Dumper. Good luck!

Replies are listed 'Best First'.
Re^3: Test if a subhash in a referenced hash exists
by Henri (Novice) on May 30, 2010 at 18:30 UTC
    wfsp, your mentioning that exists and keys need different types of input in combination with Data::Dumper got me on the right track. I checked the results of the different notations with Data::Dumper and voila! With this a major brain knot got untangled and some of the error messages are now actually starting to make sense to me.
    print Dumper($coordinates->{"AC"}{"132"}{"0"}{"coords"}); $VAR1 = { '1' => { 'value' => '4411478.623', 'name' => 'Xgeo' }, '2' => { 'value' => '5953375.013', 'name' => 'Ygeo' } };
    Here a scalar is returned. $VAR1 I think is the hash reference of the subhash.
    print Dumper(%{$$coordinates{"BD"}{"132"}{"0"}{"coords"}}); $VAR1 = '1'; $VAR2 = { 'value' => '4411478.623', 'name' => 'Xgeo' }; $VAR3 = '2'; $VAR4 = { 'value' => '5953375.013', 'name' => 'Ygeo' };
    This returns the hash contents (keys and the references of the next level subhashes) as a list.

    From how exists and defined behave, I take it that exists requires a single element, while defined is able to handle lists, too. I have to check that. But I take it I should test for the subhash reference ($hasref->) as almut pointed out and don't test the hash list itself (%{$$hasref...}).

    The refs quick ref page and the keys page were new to me, thanks for pointing me there. Most recently I have been looking at perlref, perlreftut, perlsub, perlvar, perldata and exits. Generally, most of the examples seem to deal with the topmost layer of a HoH or its final leaves layer ie. when you finally access a scalar. Examples for the middle of a HoH when you have to deal with subhashes and subarrays, however, are much rarer. Maybe it is just obvious, but to me it's not intuitive from the start. At the topmost layer you access the hash (reference) - results are from print

    $hashref # HASH(x183e2e8) %($hashref} # %{HASH(x183e2e8)} %$hashref # %{HASH(x183e2e8)}
    and you access the leaves
    $$hashref{$key1}{$key2}{$key3} # = scalar value
    In the middle you always need the extra dereference to first get at the subhash reference (a scalar) and then with it access the subhash:
    $$hashref{$key1}{$key2}{$key3} # HASH(0x18b9df8) $hashref->{$key1}{$key2}{$key3} # HASH(0x18b9df8) %($$hashref{$key1}{$key2}{$key3}} # 1HASH(0x18b9e58)2HASH(0x18b9e88)
    The following notations don’t work:
    %($hashref{$key1}{$key2}{$key3}} # Global symbol %hashref requires e +xplicit package name %$hashref{$key1}{$key2}{$key3} # syntax error

    Your comments and suggestions really helped me to cut that knot and understand a bit better what I am doing. Thanks to all of you!