ph7.0
ph7.0

Reputation: 1

Get hash keys from a multidimensional hash given partial key matches in Perl

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

Answers (2)

choroba
choroba

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

vkk05
vkk05

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

Related Questions