Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: Splitting array into two with a regex

by dragonchild (Archbishop)
on Nov 08, 2005 at 14:46 UTC ( [id://506753]=note: print w/replies, xml ) Need Help??


in reply to Splitting array into two with a regex

This is what Ruby's Array.partition() is for. You can replicate it in Perl pretty easily.
sub partition (&@) { my ($condition, @array) = @_; my (@true, @false); foreach (@array) { if ( $condition->($_) ) { push @true, $_; } else { push @false, $_; } } return \@true, \@false; } my ($ok, $no) = partition { $_[0]->name =~ m/[0-9]{2}$/ } @{ $rec->val +s };

My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

Replies are listed 'Best First'.
Re^2: Splitting array into two with a regex
by Tanktalus (Canon) on Nov 08, 2005 at 15:10 UTC

    If you're going to replicate it, can you at least make it idiomatically perl? ;-) You have the desired test value in $_ already (good!), but then you go and ruin it by passing it in. Why not just:

    sub partition (&@) { my ($condition, @array) = @_; my (@true, @false); foreach (@array) { if ( $condition->() ) { push @true, $_; } else { push @false, $_; } } return \@true, \@false; } my ($ok, $no) = partition { $_->name =~ m/[0-9]{2}$/ } @{ $rec->vals } +;

    In what is likely to be a common case, where the array is an array of strings rather than object references, that partition block becomes even more trivial. I've taken to this idiom in the last few months just because of the way it simplifies the callbacks. That it is probably faster (no parameters to pass around) actually has had no bearing on whether I use this or not (may shave off a second or two over three hours - not a concern).

      To generalize it even further:

      sub partition (&$@) { my $condition = shift; my $receivers_ar = shift; push @{ $receivers_ar->[ &$condition ] }, $_ for @_; @$receivers_ar } # Example 1: my( @good, @bad ); partition { /u/ ? 1 : 0 } [ \@good, \@bad ], qw( foo bar quux ); print "good=@good\n"; print "bad=@bad\n"; # Example 2: my @r = partition { $_ % 3 } [ [], [], [], ], 0 .. 12; for my $i ( 0 .. $#r ) { print "$i = @{$r[$i]}\n"; }
      We're building the house of the future together.
        Since we're using prototypes, another way might look like:
        sub partition (&\@\@\@) { my ($cond, $start, $true, $false) = @_; for (@$start) { push @{ $cond->() ? $true : $false }, $_; } return; } my @arr = 1 .. 9; my (@greater, @less); partition { $_ > 5 } @arr => @greater, @less; print "@greater\n@less\n";

        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        Nice. Note that Example 2 can be called as such:
        my @r = partition { $_ % 3 } [], 0 .. 12;
        and autovivification will create the sub-refs, though only for those elements that actually get assigned to. It's probably best to go ahead and specify the arrayrefs, but it could be a little cumbersome. It can be made simpler by a little tweak: the 2nd argument can be an arrayref or a number; if a number, partition creates that many sub-array(ref)s.
        sub partition (&$@) { my $condition = shift; my $receivers_ar = shift; ref $receivers_ar or $receivers_ar = [ map [], 1..$receivers_ar ]; push @{ $receivers_ar->[ &$condition ] }, $_ for @_; @$receivers_ar } my @r = partition { $_ % 3 } 3, 0 .. 12;
        Also note that the map cannot be replaced with ([]) x $receivers_ar because that will make three copies of the same ref.

        Caution: Contents may have been coded under pressure.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2024-04-19 22:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found