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

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.