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

Hi Monks!
I am trying to find if some array elements are in a hash key, to build a table alternating the text in the TDs if the name in the array match any hash key, here is a sample of what I am trying to do:
my @arr_of_names = qw(Mary John Ann); my $txt; my $table = qq|<table>|; foreach my $key ( sort(keys %$all_names )) { foreach my $name ( @arr_of_names ) { if($name eq $key) { $txt = "BAD"; $table = $table. qq|<tr><td>$txt - $key</td></tr>"; }else{ $txt = "GOOD"; $table = $table. qq|<tr><td>$txt - $key</td></tr>"; } } $table = $table. qq|</table>|; print $table;
Thanks, I hope I was clear in my question.

Replies are listed 'Best First'.
Re: Finding hash keys in array
by Grimy (Pilgrim) on May 29, 2013 at 18:42 UTC

    Looping through all the keys in the hash is very inefficient. To check if $name is a key of %$all_names, you could use :

    exists $$all_names{$name}; %$all_names ~~ $name; # Shortcut using the smartmatch operator

    Note that this isn't the same as defined $$all_names{$names}. If you do $$all_names{$key} = undef, exists would return true (because the key exists), but defined would return false (because the value is undefined).

    To select elements from an array based on a condition, you can use grep { condition } @array. Putting it all together, to get all elements of @arr_of_names that are keys of %$all_names, you can try this :

    @good = grep { %$all_names ~~ $_ } @arr_of_names;

    Note that inside the grep condition, the element being tested is aliased to $_.

Re: Finding hash keys in array
by kcott (Archbishop) on May 30, 2013 at 05:15 UTC

    Problems I found with your code:

    • Your design looks wrong: you'll be creating a table row for every key in %$all_names for every element in @arr_of_names.
    • Reading through the entire @arr_of_names for every key in %$all_names is unecessary and inefficient.
    • Assigning to $txt for every key in %$all_names for every element in @arr_of_names is unecessary and inefficient.
    • Concatenating text to $table for every key in %$all_names for every element in @arr_of_names is unecessary and inefficient.
    • You don't declare the hashref $all_names or show its data.

    Here's how I might have tackled this type of problem:

    $ perl -Mstrict -Mwarnings -le ' my @all_names = qw{Mary Ken John Ann}; my @good_names = qw{Mary John Ann}; my %all_name_data = map { $_ => 1 } @all_names; my %is_good_name = map { $_ => 1 } @good_names; print "<table>"; for (sort keys %all_name_data) { print "\t<tr><td>", $is_good_name{$_} ? "GOOD" : "BAD", " - $_</td></tr>"; } print "</table>"; ' <table> <tr><td>GOOD - Ann</td></tr> <tr><td>GOOD - John</td></tr> <tr><td>BAD - Ken</td></tr> <tr><td>GOOD - Mary</td></tr> </table>

    -- Ken

Re: Finding hash keys in array
by LanX (Saint) on May 29, 2013 at 18:01 UTC
    > Thanks, I hope I was clear in my question.

    Which question?

    There is even not a single questionmark in your post.

    Cheers Rolf

    ( addicted to the Perl Programming Language)