4

I have a array of hashes, each hash containing same keys but values are unique. On the basis of particular value, I need to store hash ref.

See the below example to understand it properly:

my @aoaoh = (
            { a => 1, b => 2 },
            { a => 3, b => 4 },
            { a => 101, b => 102 },
            { a => 103, b => 104 },
    );  

Now I will check if a hash key a contains value 101. If yes then I need to store the whole hash ref.

How to do that?

Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47

3 Answers3

16
my $key = "a";
my ($ref) = grep { $_->{$key} == 101 } @aoaoh;

or using List::Util's first():

use List::Util 'first';
my $ref = first { $_->{$key} == 101 } @aoaoh;
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • Or if you might have more than one with `a == 101`... `for my $href (grep {$_->{'a'} == 101} @aoaoh) { ### Do something with $href here }` – Oesor Apr 04 '11 at 19:36
  • Is important to define the variable like a list (of one scalar), using parenthesis around the variable. For example: my ($ref). – Jorge Olivares Jul 15 '15 at 12:38
2

Earlier, I was using foreach for fetching the Hash ref like

foreach my $href (@aoaoh){
     foreach my $hkeys(keys %{$href}){
           if(${$href}{$hkeys} == 101){
              my $store_ref = $href;
           }
     }
}

Now after taking help from eugene, i can do it like

my ($hash_ref) = grep {$_->{a} == 101 } @aoaoh;

or in general way (when we dont know the key) then use

my ($hash_ref) = grep { grep { $_ == 101 } values %$_ } @aoaoh; 
Nikhil Jain
  • 8,232
  • 2
  • 25
  • 47
1

The first method is fine and what I'd use if I only wanted to do this once or twice. But, if you want to do this many times, it's probably better to write a lookup table, like so:

my %hash_lookup;
foreach my $h ( @aoaoh ) { 
    foreach my $k ( keys %$h ) { 
        $hash_lookup{$k}{ $h->{ $k } } = $h;
    }
}

Then you find your reference like so:

my $ref = $hash_lookup{ $a_or_b }{ $value };
Axeman
  • 29,660
  • 2
  • 47
  • 102