Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

comparing array elements to hash keys

by Anonymous Monk
on Jul 02, 2003 at 14:10 UTC ( [id://270807]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I am trying to look up each element of an array in a hash, if it is present I wish to extract the corresponding values and push into a new array. I was wondering why my snippet of code won't work?! Cheers.

foreach my $thing (@array) { foreach ((my $key, my $value) = each %hash) { if ($key == $thing) { push @new_array, $value; } } }

Replies are listed 'Best First'.
Re: comparing array elements to hash keys
by Zaxo (Archbishop) on Jul 02, 2003 at 14:20 UTC

    You need to use string comparison in line 6:                       if ($key eq $thing)   { However, it would be better to check existence of the array element as a hash key, exists $hash{$_} and push @new_array, $hash{$_} for @array; replaces the whole thing. That could be done with map and grep, too: my @new_array = map {$hash{$_}} grep {exists $hash{$_}} @array; or a slice with grep, my @new_array = @hash{ grep {exists $hash{$_}} @array };

    After Compline,
    Zaxo

Re: comparing array elements to hash keys
by hardburn (Abbot) on Jul 02, 2003 at 14:24 UTC

    It probably doesn't work right because you're using the numeric comparison operator (==) on data that is probably strings. You should have used eq instead. But that's not all that you need to fix.

    The first thing that comes to mind when I look at your code is that you're not really taking advantage of true power of hashes. Instead of walking through the hash and comparing $thing to $key, you want to use $thing as the key, like this:

    foreach my $thing (@array) { if(exists $hash{$thing}) { push @new_array, $hash{$thing}; } }

    If you're not afraid of grep, try this:

    my @new_array = grep { exists $hash{$_} ? $hash{$_} : 0 } @array;

    But that will fail if %hash contains false values.

    Update: Was using $thing in the grep when I should have used $_. Thanks to davorg.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated

Re: comparing array elements to hash keys
by davorg (Chancellor) on Jul 02, 2003 at 14:33 UTC

    Much easier with grep.

    @new_array = @hash{ grep { exists $hash{$_} } @array };
    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      I was going to suggest:
      my @ary2 = grep {defined} @hash{@ary};
      It's tempting to just say   my @ary2 = @hash{@ary}.   But the values in @ary that don't match keys in %hash produce undefined values that have to be weeded out.

      Here's a quick demo:

      #!/usr/bin/perl -w use strict; my @ary = ('a', 'c', 'g', 'l'); my %hash = (a => 1, b => 2, c => 3, d => 4); my @ary2 = grep {defined} @hash{@ary}; print "[$_]\n" for @ary2;
Re: comparing array elements to hash keys
by CukiMnstr (Deacon) on Jul 02, 2003 at 14:21 UTC
    you have to change the foreach in your inner loop for a while (right now it is only iterating once over the hash), or change the foreach inner loop to use keys %hash instead of each %hash (so it iterates over every key). Also, you are using == to compare the elements in the array to the keys in the hash, so this will only work for numeric values. You could try something like this instead:
    foreach my $thing (@array) { if ( exists $hash {$thing} ) { push @new_array, $hash {$thing}; } }

    hope this helps,

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://270807]
Approved by particle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (1)
As of 2024-04-25 00:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found