Dr. Claus-Peter Becke wrote:
> foreach (/(\w+)/i) {
> push @words,$&;
> }
> print $q->popup_menu('to_thesaurus', @words);
>
> this solution succeeds in finding and returning the last element...
There are a few problems here:
1. regex should use the /g modifier to find all matches in the string
(note - the /i is not needed because \w matches upper and lower case)
without the /g the pattern match will return only the first word
2. with no variable listed in the foreach and relying on $& you always
get the same value on each iteration because the pattern match returns a
list of matches on the first iteration and $& never changes inside the
loop
So, your for loop should look like this:
foreach my $word (/(\w+)/g) {
push @words,$word;
}
This is a bit subtle - the regex returns the list of words, so is the
sentence was "hi there" the first iteration of the foreach would receive
(one two) from the pattern match, but the $& variable is set to the last
successful match. Although the loop iterates twice, $& is set to the
last word on the first iteration of the loop.
$_ = 'hi there';
foreach (/(\w+)/g) {
print "\$_ => ($_) \$& => ($&)\n";
push @words,$&;
}
print join ":", @words;
print "\n", scalar @words, " words in sentence\n";
will print:
$_ => (hi) $& => (there)
$_ => (there) $& => (there)
there:there
2 words in sentence
Adding the variable to the foreach so it is:
foreach my $word ... results in each of the values returned by the
pattern match being assigned to $word
foreach my $word (/(\w+)/g) {
print "\$_ => ($_) \$word => ($word)\n";
push @words,$word;
}
prints:
$_ => (hi there) $word => (hi)
$_ => (hi there) $word => (there)
hi:there
2 words in sentence
Generally speaking you are better off *not* using $&.
There is another problem not related to the regex. The second parameter
to the popup_memu should be a *reference* to a list. You should either
enclose the array in square brackets or pass it as [EMAIL PROTECTED]
print $q->popup_menu('to_thesaurus', [EMAIL PROTECTED]);
Otherwise you will only get the first item in the array.
If the purpose of this code is to provide a menu for lookup in a
thesaurus you might want to consider producing a list of unique words
instead of listing all of the words in the sentence. Using a hash would
provide unique values, but they would not be in the same order as the
words appeared in the sentence. Here is some code that will produce an
array with a unique list of the words in the sentence in order of their
appearance:
$sentence = $q->query_string(); # using $_ can be troublesome
my @list = split / /, $sentence;
my %used;
foreach my $item (@list) {
if (my ($word) = $item =~ /(\w+)/) {
push @words, $word unless $used{$word};
$used{$word} = 1;
}
}
with $sentence = 'she had brown hair and brown eyes';
@words would be: she:had:brown:hair:and:eyes
Perhaps I've had too much caffeine this morning ;-)
Happy hacking,
Mike Williams
ps - always include use warnings; and use strict; in your perl code
unless you *like* chasing bugs
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>