views:

285

answers:

5

I need to get all of the values for a certain key in a hash. The hash looks like this:

$bean = {
     Key1 => {
               Key4 => 4,
               Key5 => 9,
               Key6 => 10,
             },
     Key2 => {
               Key7 => 5,
               Key8 => 9,
             },
};

I just need the values to Key4, Key5 and Key6 for example. The rest is not the point of interest. How could I get the values?

Update: So I don't have a %bean I just add the values to the $bean like this:

 $bean->{'Key1'}->{'Key4'} = $value;

hope this helps.

+3  A: 
foreach my $key (keys %{$bean{Key1}})
{
  print $key . " ==> " . $bean{Key1}{$key} . "\n";
}

should print:

Key4 ==> 4
Key5 ==> 9
Key6 ==> 10
tster
didn't work for my case Bean is my Hashits build like$bean->{'Key1'}and i need all the values from that key.
Przemek
@Przemek: if the only difference is the capitalization, you should be able to adjust that pretty easily. (Your question originally said 'Bean', and case matters.)
Telemachus
`$bean{Key1}{$key}` should be `$bean->{Key1}{$key}`, no?
Arkadiy
True, the problem keeps changing, so I'm not going to update the answer any more.
tster
@Arkadiy: When the OP first put up the problem, the key variable name was Bean - uppercase and with no sigil. Other people have since gone back and forth, making it either a reference or a hash. So, it's completely unclear what the OP really has.
Telemachus
found a bug in my part and finally this solution worked for my problem! thanks to you guys for the help.
Przemek
+2  A: 

If %bean is a hash of hashes, $bean{Key1} is a hash reference. To operate on a hash reference as you would on a simple hash, you need to dereference it, like this:

%key1_hash = %{$bean{Key1}};

And to access elements within a hash of hashes, you use syntax like this:

$element = $bean{Key1}{Key4};

So, here's a loop that prints the keys and values for $bean{Key1}:

print $_, '=>', $bean{Key1}{$_}, "\n" for keys %{$bean{Key1}};

Or if you just want the values, and don't need the keys:

print $_, "\n" for values %{$bean{Key1}};

See the following Perl documentation for more details on working with complex data structures: perlreftut, perldsc, and perllol.

FM
A: 

A good way to do this - assuming what you're posting is an example, rather than a single one off case - would be recursively. So we have a function which searches a hash looking for keys we specify, calling itself if it finds one of the values to be a reference to another hash.

sub recurse_hash {
  # Arguments are a hash ref and a list of keys to find
  my($hash,@findkeys) = @_;

  # Loop over the keys in the hash
  foreach (sort keys %{$hash}) {

    # Get the value for the current key
    my $value = $hash->{$_};

    # See if the value is a hash reference
    if (ref($value) eq 'HASH') {
      # If it is call this function for that hash
      recurse_hash($value,@findkeys);
    }

    # Don't use an else in case a hash ref value matches our search pattern
    for my $key (@findkeys) {
      if ($key eq $_) {
        print "$_ = $value\n";
      }
    }
  }
}

# Search for Key4, Key5 and Key6 in %Bean
recurse_hash(\%Bean,"Key4","Key5","Key6");

Gives this output:

Key4 = 4
Key5 = 9
Key6 = 10
Dave Webb
Recursion is in fact a terrible way to do that.
friedo
@friedo - Why is it a terrible way?
Dave Webb
@Dave, because you are unnecessarily accumulating stack frames to traverse a structure of known depth. And even if the structure had an arbitrary depth, an iterative approach would be far more efficient. That's the reason why functional languages like Haskell have tail-call optimization.
friedo
@friedo - I think the point of this answer is that it assumes arbitrary depth. And although an iterative solution might be more efficient, a recursive solution is more natural, and worrying about stack frames might be premature optimization.
runrig
obligatory mention of Data::Diver
ysth
A: 

Yet another solution:

for my $sh ( values %Bean ) {
    print "$_ => $sh->{$_}\n" for grep exists $sh->{$_}, qw(Key4 Key5 Key6);
}
Hynek -Pichi- Vychodil
+1  A: 

See the Perl Data Structure Cookbook for lots of examples of, well, working with Perl data structures.

brian d foy