Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks, I am trying to figure out a way to check whether each value in an array is present in a hash -i then want to extract both key and value if it exists. Could anyone help? Much appreciated ;-o
my @array; # contains various numbers my %hash = map {$numbers[$_] => $temps[$_]} 0 .. $#numbers; while (($key, $value) = each (%hash)) { if ($key == $array[$_]) { push @found, $key . $value; } }

Replies are listed 'Best First'.
Re: hashes: testing for the presence of a key
by Ovid (Cardinal) on May 15, 2003 at 14:01 UTC

    See 'perldoc -f exists'. That will tell you if a given scalar is a key in an array.

    What do you mean by "extract", though? Do you mean that you want the array to be altered?

    @array = grep { ! exists $hash{$_} } @array;

    Update: That first sentence should end with "in a hash". Thanks to VSarkiss for the typo catch :)

    Cheers,
    Ovid

    New address of my CGI Course.
    Silence is Evil (feel free to copy and distribute widely - note copyright text)

Re: hashes: testing for the presence of a key
by broquaint (Abbot) on May 15, 2003 at 14:00 UTC
    use Data::Dumper; my @array = qw/ foo bar baz quux /; my %hash = qw/ foo one quux two /; my @found = map { $array[$_] . $hash{$array[$_]} } grep { exists $hash{$array[$_]} } 0 .. $#array; print Dumper(\@found); __output__ $VAR1 = [ 'fooone', 'quuxtwo' ];
    See. the exists, map and grep docs for more info.
    HTH

    _________
    broquaint

Re: hashes: testing for the presence of a key
by jdporter (Paladin) on May 15, 2003 at 14:11 UTC
    The essence of the answer is to iterate over the array of various numbers (@array) and test for each in the hash, rather than vice versa, which is what you attempted to do. It is easier both to iterate over an array, and to test for existence in a hash.
    for ( @array ) { if ( exists $hash{$_} ) { push @found, $_ . $hash{$_}; } }
    You could reduce the above to this:
    push @found, map { $_ . $hash{$_} } grep { exists $hash{$_} } @array;
    Or even
    push @found, map { exists $hash{$_} ? $_ . $hash{$_} : () } @array;

    jdporter
    The 6th Rule of Perl Club is -- There is no Rule #6.

      Unless @found has pre-existing contents, you can drop the push as well.

      my @a = ( 1, 3, 5, 7, 9, 11 ); my @hash{ 1 .. 10 } = 'a' .. 'j'; my @found = map{ exists $hash{$_} ? "$_$hash{$_}" : () } @a; print "@found"; 1a 3c 5e 7g 9i

      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller