Reputation: 6123
I'm trying to learn Perl better, and learn hash slices.
Instead of 3 different if (defined
statements, I'm trying to tidy the code to make it more maintainable and readable, but have come across the following conundrum:
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie ':all';
use Carp 'confess';
use DDP; # a.k.a. Data::Printer
use JSON 'decode_json';
my $hashref;
$hashref->{Jane} = decode_json('{"sex":"Female","Mortality_Status":"Alive", "latest_date":"2020-11-26","Hospitalized":"no","Risk_Status":"NA"}');
p $hashref; # pretty print the data
my @needed_terms = qw(age BMI sex);
if (defined @{ $hashref->{Jane} }{@needed_terms}) {
say 'all terms are defined.'; # this is what it says, which is WRONG!!!
} else {
say 'some terms are missing.'; # Jane is missing BMI and age, so the script should print here
}
I've read How to do sum of hash reference slice? and https://perlmonks.org/?node=References+quick+reference to no avail.
This person Jane
is missing both age
and BMI
information, so the if (defined
statement should say that some terms are missing, but is instead passing.
I get the same error whether I use @{ $hashref->{Jane} }{@needed_terms}
or %{ $hashref->{Jane} }{@needed_terms}
I've also thought that maybe defined
is returning how many terms of the slice are defined, but that isn't true.
How can I set if (defined
statement on a hash slice properly?
Upvotes: 4
Views: 111
Reputation: 62227
This is a good place to use all
from List::Util:
use List::Util qw(all);
if (all { exists $hashref->{Jane}{$_} } @needed_terms) {
say 'all terms are defined.';
} else {
say 'some terms are missing.'; # Jane is missing BMI and age, so the script should print here
}
It loops through all the needed terms and checks to see if each exists as key to the Jane
hash.
One of my favorite docs for Perl Data Structures is perldoc perldsc. It is more of a step-by-step tutorial than References quick reference.
Upvotes: 3