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

Monks

@arr2 =('a', 'b'); @arr1 = ('a'); for $var1 (@arr2) { if( grep($var1, @arr1) ) { print "match $var1\n"; } } output: match a match b
Huh???

surely only the 'a' should match?

Cheers
Chris

Replies are listed 'Best First'.
Re: Weird grep behaviour
by shmem (Chancellor) on Oct 17, 2007 at 06:16 UTC
    If you want a match, do a match. Use
    if( grep(/$var1/, @arr1) )

    or

    if( grep {/$var1/} @arr1 )

    or

    if( grep { $_ eq $var1} @arr1 )

    Your usage of grep evaluates $var1 for every instance of @arr1, then happily returns the element for which the evaluation of $var1 succeeded. See grep.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Weird grep behaviour
by Krambambuli (Curate) on Oct 17, 2007 at 08:08 UTC
    The following might surprise you:
    use strict; use warnings; use Data::Dumper; my @arr1 = ('a'); my $var1 = 'b'; my (@surprise) = grep($var1, @arr1); print Dumper( \@surprise );
    Just re-read grep. Remember that grep uses a boolean filter - the first argument - to select values out of a list. Your 'filter' - $var1 - always evals to TRUE.

    If seems that what you are looking for might be something like
    use strict; use warnings; my @arr2 =('a', 'b'); my @arr1 = ('a'); my %reference = map { $_ => 1 } @arr1; for my $var1 (@arr2) { print "match $var1\n" if exists $reference{$var1}; }
    Hth.
Re: Weird grep behaviour
by moritz (Cardinal) on Oct 17, 2007 at 05:56 UTC
    Try grep {$var1 eq $_ } instead.

    My guess is that grep uses numerical comparison if called with an EXPR (and not a BLOCK), so "a" == "b".

      No, it's just that $var1 is "true" for every element in @arr1. There's no comparison in the OP.

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      It's not about comparison, BLOCK and EXPR are evaluated in boolean context. From OP's sample code, in grep($var1, @arr1), $var1 is always true.

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Re: Weird grep behaviour
by chrism01 (Friar) on Oct 17, 2007 at 06:55 UTC
    According to the Perl manpage:
    "In particular, it is not limited to using regular expressions"
    Changing it to use a regex ( /$var1/ ) worked, but I still don't understand why it didn't previously.

    Chris

      You grep expression is in the form:grep EXPR,LIST. But EXPR is fixed as $var1 - not a regexp or code block.

      grep will return the whole list or an empty list depending on whether $var evaluates to true or false. Consider:

      my @arr1 = ('a'); foreach my $var1 (0, 1) { if( grep($var1, @arr1) ) { print "match $var1\n"; } else { print "fail $var1\n"; } }
    • nothing is returned when $var1 is 0 (false)
    • the entire list is returned when $var1 is 1 (true)
    • Update: Here's a sample usage:

      #!/usr/bin/perl use warnings;use strict; my $paid = 0; # :-( my @shopping = ( 'twinkies','coffee', (grep !$paid => 'gruel', 'cabbage', 'cordial'), (grep $paid => 'caviar', 'truffles', 'champagne'), ); print "@shopping";
      Well, I think because your filter was so loose everything gets through. With /$var1/, the filter is pretty strict.

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

A reply falls below the community's threshold of quality. You may see it by logging in.