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

Hi monks, I am looking through an array, finding the first value that passes a test and pushing it into annother array. However, my question is, how can I get save everything after the match into a new array?? Thanks a lot!
my $size = @array; for (my $i=1; $i < @array; $i++) { if (($array[$i] <0) && ($array[$i-1] > 0)) { push @found, "$array[$i-1] $array[1]"; # want to get from $i+1 to end of array # tried: push @rest, "$array[$i+1] .. $array[$size]"; } }
  • Comment on Finding the first element that passes a test - then saving the rest.
  • Download Code

Replies are listed 'Best First'.
Re: Finding the first element that passes a test - then saving the rest.
by broquaint (Abbot) on Jun 05, 2003 at 10:58 UTC
    In your particular case just take advantage of the last statement e.g
    my @found; for (0 .. $#array) { if ($array[$_] < 0 and $array[$_ - 1] > 0) { @found = @array[$_ .. $#array]; last; } }

    HTH

    _________
    broquaint

      broquaint: this appears to fail for an array such as ( -1, -2, 10, -3, 2 ), because on the first iteration (when $_ == 0 ), $_ - 1 is the last element of the array:

      my @ary = qw ( a b c 2); print $ary[-1];

      Please correct (and downvote accordingly :-) if I've missed something

      dave

Re: Finding the first element that passes a test - then saving the rest.
by larsen (Parson) on Jun 05, 2003 at 11:33 UTC
    Just an outlined hint, but you could use recursion and Perl's ability to store the returned list in separate variables.
    use strict; use warnings; sub beaver_find { my ($cond, @l) = @_; return () unless @l; my $head = shift @l; return $cond->( $head ) ? ($head, @l) : beaver_find( $cond, @l ); } my $cond = sub { my $x = shift; return $x > 0 }; my @l = ( -1, -3, -2, 10, -1, -3, -2 ); my( $head, @tail ) = beaver_find( $cond, @l ); print qq| Head: $head Tail: @tail |;
Re: Finding the first element that passes a test - then saving the rest.
by particle (Vicar) on Jun 05, 2003 at 13:55 UTC

    this should do what you want. also, it will work if a zero value is found in the data, which fails with your current test. i've included some test data and examples.

    #!/usr/bin/perl use strict; use warnings; $|++; sub to_zero_or_below { ## must have a two element list to process return unless 2 <= @_; for my $index ( 1..$#_ ) { ## skip unless i've decended to zero or below next unless $_[$index - 1] > 0 and $_[$index] <= 0; ## return the remainder of the list return @_[$index..$#_]; } } my @data= ( -3, -1, 1, 3, 2, 1, 0, -1, -2 ); ## zero present print $_, $/ for to_zero_or_below( @data ); print "~~~\n"; ## no zero print $_, $/ for to_zero_or_below( reverse @data );

    ~Particle *accelerates*

Re: Finding the first element that passes a test - then saving the rest.
by jmm (Initiate) on Jun 05, 2003 at 15:05 UTC
    As long as the test depends only on the individual element, you can use the flip-flop operator "..".
    @ans = grep { ($_ > 0) .. 0 } @array; $found = shift @ans;