Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

grep { $var } @arr

by igelkott (Curate)
on Jul 17, 2014 at 14:46 UTC ( #1094064=perlquestion: print w/ replies, xml ) Need Help??
igelkott has asked for the wisdom of the Perl Monks concerning the following question:

Is it possible to use a variable in place of the expression or block of grep? Am I missing something simple or is this simply illegal?

With the simple fragment below, I would like to get a result of 1,2 for both greps but I get all elements on the second. Btw, I get the same results from the expression version: "grep $var, @arr".

use strict; use warnings; my @arr = (1, 2, 3, 4, 5); my $pat = '$_ < 3'; my @res; @res = grep {$_ < 3} @arr; print "Literal:\t@res\n"; @res = grep {$pat} @arr; print "Variable:\t@res\n";

Of course, this is just a test script. The real thing builds the grep pattern in several steps and searches a two-dimensional array. I could do all this differently but the most obvious alternative would be a long list of if statements.

Comment on grep { $var } @arr
Select or Download Code
Replies are listed 'Best First'.
Re: grep { $var } @arr
by Athanasius (Abbot) on Jul 17, 2014 at 14:56 UTC

    Another option is to use a subroutine reference instead of a string:

    #! perl use strict; use warnings; my @arr = (1, 2, 3, 4, 5); my $pat = sub { $_[0] < 3 }; my @res; @res = grep {$_ < 3} @arr; print "Literal:\t@res\n"; @res = grep { $pat->($_) } @arr; print "Variable:\t@res\n";

    Output:

    0:52 >perl 939_SoPW.pl Literal: 1 2 Variable: 1 2 0:52 >

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: grep { $var } @arr
by toolic (Bishop) on Jul 17, 2014 at 14:53 UTC
    eval seems to work (with the usual security disclaimers):
    @res = grep {eval $pat} @arr;
      eval $pat

      Thanks! I feel like a total fool but it's worth having such a simple fix.

      This works on my overly complex, multi-dimensional problem as well.

Re: grep { $var } @arr
by LanX (Canon) on Jul 17, 2014 at 14:58 UTC
    > Am I missing something simple or is this simply illegal?

    Its code, so put it into a function. grep allows replacing the EXPR with a function call and $_ is global anyway. :)

    Cheers Rolf

    (addicted to the Perl Programming Language)

Re: grep { $var } @arr
by Anonymous Monk on Jul 17, 2014 at 14:58 UTC

    You are not using a pattern which, to me, implies m// or index() use; you are actually using a code block.

    Use a list of sub references to iterate over instead ...

    @test = ( sub { $_[0] < 3 } ); for my $t ( @test ) { print join q[ ] , grep $t->( $_ ), 1 .. 5; }
Re: grep { $var } @arr
by bulrush (Beadle) on Jul 17, 2014 at 16:53 UTC
    Yes you can do that but I usually do it like this:
    @res = grep (/$pat/g, @arr);
    
    Perl 5.8.8 on Redhat Linux RHEL 5.5.56 (64-bit)
      Well, bulrush, you did not say how you populate $pat, but I fail to see how a regex would figure out whether a value is larger or smaller than 3.

      I definitely agree that a subroutine reference is a very good solution, perhaps the best.

        I fail to see how a regex would figure out whether a value is larger or smaller than 3.

        You can get clever with match-time pattern interpolation. For instance:

        my @list = (1..5); my $pattern = qr/\d+(??{if($& < 3) { "" } else { "(?<!\\d)" } })/; my @res = grep /$pattern/, @list; say join ", ", @res;

        This also (ab)uses negative look-behind assertions to create a subpattern that is guaranteed to fail (in this regex, not in general).

        But I agree, subroutine references are the way to go here.

      /$pat/g

      Perhaps I've misunderstood but with my current $var, using /$pat/g will result in no matches (with or without the 'g' modifier). As far as I know, this will look for the literal string of '$_ < 3' on my array, as written below (appending to the initial script).

      @res = grep {/$pat/g} @arr; print "Search:\t@res\n";

      This finds none of the elements of @arr.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1094064]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (17)
As of 2015-07-31 21:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (282 votes), past polls