Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

grep2 (like 'grep', but also return non-matches)

by blahblahblah (Priest)
on Jan 14, 2005 at 17:38 UTC ( #422328=snippet: print w/replies, xml ) Need Help??
Description: Pretty simple, but I find it useful:
my @all = ('a', 'b', 'c', '1', '2', '3'); my ($numbers, $letters) = grep2 {/\d/} @all; print "numbers: @$numbers\n"; # prints "1 2 3" print "letters: @$letters\n"; # prints "a b c"

sub grep2 (&@)
{
    my $code = shift;
    my $true = [];
    my $false = [];
    foreach (@_)
    {
        if (&{$code}())
        {
            push @$true, $_;
        }
        else
        {
            push @$false, $_;
        }
    }
    return ($true, $false);
}

my @all = ('a', 'b', 'c', '1', '2', '3');
my ($numbers, $letters) = grep2 {/\d/} @all;

print "numbers: @$numbers\n";  # prints "1 2 3"
print "letters: @$letters\n";  # prints "a b c"
print "all: @all\n";
Replies are listed 'Best First'.
Re: grep2 (like 'grep', but also return non-matches)
by ccn (Vicar) on Jan 14, 2005 at 18:30 UTC

    Nice one.

    The same but little bit more shortly:

    sub grep2 (&@) { my $code = shift; my ($true, $false) = ([], []); push @{ &{$code}() ? $true : $false }, $_ for @_; return ($true, $false); }
Re: grep2 (like 'grep', but also return non-matches)
by belg4mit (Prior) on Jan 16, 2005 at 15:05 UTC
    For short lists it probably makes more sense to just traverse the list twice, once with the the test negated... rather than dealing with references.

    --
    I'm not belgian but I play one on TV. On dit que je parle comme un belge aussi.

Re: grep2 (like 'grep', but also return non-matches)
by BrentDax (Hermit) on Jan 24, 2005 at 19:32 UTC

    You might be interested in my List::Part module, which basically does the same thing in a more general way.

    use List::Part; ($letters, $numbers)=part { /\d/ } qw(a b c 1 2 3);

    The main function of the module looks like this:

    sub part(&@) { my $code=shift; my @ret; for(@_) { my $i=$code->($_); next unless defined $i; push @{$ret[$i]}, $_; } return @ret; }

    =cut
    --Brent Dax
    There is no sig.

      Could I please ask that anyone who plays with $_ like this ... please localise it?

      sub part(&@) { my $code=shift; my @ret; local $_; for(@_) { my $i=$code->($_); next unless defined $i; push @{$ret[$i]}, $_; } return @ret; }

      Thanks. There are some really hard-to-figure-out bugs that creep up on people when the subs they call go and affect $_ like this.

      Tanktalus, twice bitten, once shy. Or something like that.

        perlsyn sez about foreach:

        ...the variable is implicitly local to the loop and regains its former value upon exiting the loop.

        So I think this is quite safe.

        =cut
        --Brent Dax
        There is no sig.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: snippet [id://422328]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2022-05-28 11:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (99 votes). Check out past polls.

    Notices?