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

Hi monks,

Can anyone tell me if it is somehow possible to do the following without looping through the array?
#!/usr/bin/perl use strict; use warnings; my @bah = ( "Australia", "Austria", "Finland", "Norway" ); my $foo = "In Australia the people from Austria drink beer at the pub +with the people from Norway"; my $result = ""; foreach my $match (@bah) { if ($foo =~ /\Q$match\E/ig) { $result .= $match . " "; } # end-if } # end-foreach print $result, "\n"; exit; # Result = Australia Austria Norway
Cheers,
Reagen

Replies are listed 'Best First'.
Re: regex matching using arrays
by zejames (Hermit) on Dec 04, 2004 at 10:58 UTC

    Yes you can, by using logical OR in regex

    use strict; use warnings; my @bah = ( "Australia", "Austria", "Finland", "Norway" ); my $regex = join ('|', map { "(?:$_)" } @bah); my $foo = "In Australia the people from Austria drink beer at the pub +with the people from Norway"; my $result = ""; my @data = $foo =~ /($regex)/g; print join ", ", @data;

    HTH


    --
    zejames
      Cool, thanks zejames.
      Do you know if there is a limit on the size that $regex can take? i.e. if the array is really big will it break things?
        Your regex will extend up to the maximum size of your scalars.. which can go past the size of your physical memory! However, I'm sure after a few hundred OR clauses the regex will get bloody slow. You should probably bench it.
        Of course, that loops over the array twice (map and join)
        Do you know if there is a limit on the size that $regex can take? i.e. if the array is really big will it break things?
        If you have a large word list, and you're trying to determine which of those words occur in a given text of arbitrary length, the best approach is likely to be to store the word list in a hash, then tokenize the text string; for each tokenized word in the string, if that word exists as a hash key, you've got a hit (append that word to your output list).

        This way, you've got one simple loop over the "lexicon" (to store the word list as hash keys), and one loop over the word tokens in the text string; you're doing plain string comparisons (best to put everything in monocase) instead of regex matches, so it should be pretty quick.

Re: regex matching using arrays
by TedPride (Priest) on Dec 05, 2004 at 03:30 UTC
    I'm assuming you're trying to get a list of which words are present in the text. substr is faster than regex for this, and lowercase searching is faster than case insensitive, so:
    use strict; use warnings; my @bah = ( "Australia", "Austria", "Finland", "Norway" ); my $foo = "In Australia the people from Austria drink beer at the pub +with the people from Norway"; $foo = lc($foo); my @f; for (@bah) { push @f, $_ if index($foo, lc($_)) != -1; } print join(' ', sort @f), "\n";
    I really don't think you're going to be able to get out of looping somewhere in the code, though.