SPUG: Slice of HashOfHash
Jacinta Richardson
jarich at perltraining.com.au
Thu Nov 16 03:27:45 PST 2006
David Dyck wrote:
>> but the if statement is somewhat unsafe. in the case where the subhash
>> doesn't have a key named 'husband', it will be autovivified. this may
>> or may not be a problem.
>
> The above _may_ have been true at some version of perl (as I used to
> write code like below also (using exists) - but it is not now the case when
> I test the code. I you find a perl doing this (where
> if ( $hash->{ exhusband } eq 'fred' )
> autovivifies some element in %HoH), please let me know, as I couldn't
> create a test case with recent (6 year old) perl version where the
> if test needed the exists check that you gave below.
I agree that the proposed if statement doesn't cause auto-vivication, but it's
important to be aware that it *will* cause a warning to be generated if warnings
are turned on. Comparing an undefined thing to a string does that. ;) This
isn't a big deal but most people don't like their code generating warnings, so
Jerry's advice (to check the field first ) is right... just for the wrong
reason. Of course, we can also just check it for truth and save a few characters.
My personal solution to the given problem is:
foreach my $key ( keys %HoH ) {
if($Hoh{$key}{husband} && $HoH{$key}{husband} eq "fred") {
print "yes\n";
}
}
The main difference being that I don't understand why someone would recommend
taking a hash slice of the whole hash when we can just iterate over the keys. I
suspect Damian Conway would suggest instead that we iterate over the values:
foreach my $value ( values %HoH ) {
if($value->{husband} && $value->{husband} eq "fred") {
print "yes\n";
}
}
because he doesn't like the extra work of dereferencing when values() does the
work for us. It's in the PBP book which I don't have handy right now. He's
right, but I still prefer keys().
I think the original poster was asking whether there's a way to do something
like this:
foreach my $husband ( @{$HoH{ _ }{husband} ) {
if( $husband eq "fred" ) {
print "yes\n";
}
}
Such that Perl iterates over all the keys and pulls out the husband for each
subhash for us. It would be cool, I've wanted to do it myself a few times, but
no; there's no way specifically like that. But it's not much less code than the
other solutions either.
All the best,
Jacinta
More information about the spug-list
mailing list