G'day Bman70,
Welcome to the Monastery.
my %hash = @allwords; #puts array in hash to search / compare.
That's not doing what you think. You'll end up with a hash that looks something like this:
( 'word1' => 'word2', 'word3' => undef, )
Here's an example (see Data::Dump, which exports the dd function, if you're unfamiliar with that module; see perlrun for '-M' and all other command switches):
$ perl -MData::Dump -e '@a = qw{b c a}; %h = @a; dd \%h' { a => undef, b => "c" }
The usual idiom uses map:
my %hash = map { $_ => 1 } @allwords;
Extending that first example:
$ perl -MData::Dump -e '@a = qw{b c a}; %h = map { $_ => 1 } @a; dd \% +h' { a => 1, b => 1, c => 1 }
if (exists $hash{'word1' && 'word2' && 'word3'}) { ...
That's not working because "'word1' && 'word2' && 'word3'" evaluates to "'word3'"; your condition effectively becomes "exists $hash{'word3'}". Here's an example of that:
$ perl -E 'my $x = "a" && "b" && "c"; say $x' c
if ( grep { $_ eq 'word1' && 'word2' } @allwords ) { ...
That suffers from much the same problem as the previous point:
$ perl -E '$_ = "a"; my $x = $_ eq "a" && "b"; say $x' b
A typical method of determining how Perl evaluates your code is with B::Deparse. It's usually run from the command line; using the "-p" option is often useful, and seeing the results with and without this option can often provide additional insight. Here's how Perl sees your grep code:
$ perl -MO=Deparse -e 'grep { $_ eq "word1" && "word2" } @a' grep {'word2' if $_ eq 'word1';} @a; -e syntax OK $ perl -MO=Deparse,-p -e 'grep { $_ eq "word1" && "word2" } @a' grep({(($_ eq 'word1') and 'word2');} @a); -e syntax OK
I suggest you read through "perlintro - Perl introduction for beginners". It will help you with some of the basic mistakes you've made. It also has many links to more detailed documentation and advanced topics: this makes it a handy reference for future (repeat) use.
That covers all the issues you had with your various attempts at a solution. I see a number of working solutions have already been provided. Here's how I might have solved this (assuming all the elements of your array are unique) using grep in scalar context.
$ perl -E 'my @x = qw{b c a}; say scalar grep { /^(?:a|b|c)$/ } @x' 3 $ perl -E 'my @x = qw{x y z}; say scalar grep { /^(?:a|b|c)$/ } @x' 0 $ perl -E 'my @x = qw{x c y a b z}; say scalar grep { /^(?:a|b|c)$/ } +@x' 3
You can force scalar context with an operator; allowing you to write your if condition like this:
my $regex = ...; if (@matchwords == grep { /$regex/ } @allwords) { ...
In the examples, I gave the regex as an alternation (/^(?:a|b|c)$/) for illustrative purposes. I assume your wordN values are just test data. For your real code, a similar alternation may be appropriate; however, something like /^word[1-3]$/ or /^word\d+$/ may be better. If you think the alternation is the best choice for you, consider creating $regex dynamically from @matchwords: see "Building Regex Alternations Dynamically" for details of how to do this.
Finally, when choosing your solution, you may find Benchmark useful.
— Ken
In reply to Re: Check array for several matches
by kcott
in thread Check array for several matches
by Bman70
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |