4

Is there a grep-like function that splits a list into both the part that matches the expression, as grep does, and also its complement?

Of course it would be very simple to write such a function, but I'm interested to know if it already exists and would be more conveniently included from any of the List::Util-like modules.

Anna
  • 2,645
  • 5
  • 25
  • 34

2 Answers2

6

I found the answer browsing through List::MoreUtils right after posting the question (my apologies). It's part:

Partitions LIST based on the return value of BLOCK which denotes into which partition the current value is put. Returns a list of the partitions thusly created. Each partition created is a reference to an array.

my $i = 0;
my @part = part { $i++ % 2 } "a".."h";   # Returns [qw( a c e g )], [qw( b d f h )]
ikegami
  • 367,544
  • 15
  • 269
  • 518
Anna
  • 2,645
  • 5
  • 25
  • 34
5

If you're in an environment that won't let you install modules, here's a version of List::MoreUtils::part that doesn't depend on anything:

#!/usr/bin/env perl
use warnings;
use strict;
use feature qw/say/;

sub part(&@) {
    my $f = shift;
    my @parts;
    for (@_) {
        my $bucket = $f->();
        push @{$parts[$bucket]}, $_;
    }
    return @parts;
}

my ($evens, $odds) = part { $_ % 2 } 1..10;
say "Even numbers: @$evens";
say " Odd numbers: @$odds";
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • 1
    @TLP The original also has a XS implementation that's faster and should be preferred unless you have grumpy sysadmins. (Note I wasn't trying to play code golf) – Shawn Jun 22 '22 at 13:21