Reputation: 1
Newbie here. I am trying to get the first key from a hash of hashes. Say I construct a hash of hashes like following:\
%hash;
$first_key;
$hash{'First'}{'Float'}=0.1;
$hash{'First'}{'XY'}='X0Y0';
$hash{'First'}{'Score'}=100;
I use
$hash{$_}{'Float'} eq 0.1 && $hash{$_}{'XY'} eq 'X0Y0'
and $first_key = $_ for keys %hash;
to find the first key when there’s only one.
But how do I get an array or loop to get the first key if there is multiple matches with $hash{$_}{'Float'} eq 0.1 && $hash{$_}{'XY'} eq 'X0Y0'
if there’s another set like the following:
$hash{'Second'}{'Float'}=0.1;
$hash{'Second'}{'XY'}='X0Y0';
$hash{'Second'}{'Score'}=90;
Thanks in advance.
Upvotes: 0
Views: 187
Reputation: 241918
Use grep to select from a list:
my @matching_keys = grep $hash{$_}{Float} == 0.1 && $hash{$_}{XY} eq 'X0Y0',
keys %hash;
You can use the same to select the first one:
my ($first) = grep ...
The parentheses are needed to keep grep
in the list context, as in scalar context, it returns the number of matches. You can use a list subscript instead:
my $first = (grep ...)[0];
Alternatively, you can use first
from List::Util which is not context sensitive:
use List::Util qw{ first };
my $first = first {
$hash{$_}{Float} == 0.1 && $hash{$_}{XY} eq 'X0Y0'
} keys %hash;
Note that I used eq
for strings, but ==
for numbers. For floats, even ==
can be tricky due to imprecision.
Upvotes: 6
Reputation: 3222
Here is another way to achieve the same.
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw{ first };
my %hash = (
"First" => {
"Float" => "1",
"XY" => "X0Y0",
"Score" => "100"
},
"Second" => {
"Float" => "0.1",
"XY" => "X0Y0",
"Score" => "90"
},
);
foreach my $key (keys %hash){
if(($hash{$key}{"Float"} == 0.1) && ($hash{$key}{"XY"} eq 'X0Y0')){
print "First Matched Key:$key";
last;
}
}
Please Note:
Comparison operators (equal) for numbers and strings are achieved using ==
and eq
respectively.
Upvotes: 0