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

Hi Monks,

I can't work out what is wrong with my loop. I'm simply iterating through an array called @pids (630 items). I want to get those items that match things in a different array and those that don't seperately.

I get 400 items in @hits as expected but the full 630 items in the @potential_hgt array (when it should be finding 230).

Can someone please advise where i'm going wrong?

cheers

foreach my $orth (@orthologs) { my $hit; if ($orth =~ /^A(\d+)/) { $hit=$1; } + + for (my $i=0; $i<@pids; $i++) { if ($pids[$i] =~ /$hit/) { push @hits, $hit; } else { push @potential_hgt, $pids[$i]; } } }

Replies are listed 'Best First'.
Re: for loop trouble
by Corion (Patriarch) on Aug 12, 2005 at 09:59 UTC

    Your $hit variable is undefined if your $orth variable doesn't match /^A(\d+)/. You might want to check for that.

    Also, you seem to come from a C-like programming language. The loop could be written in a shorter, less error-prone way as

    push @hits, grep {/$hit/} @pids; push @potential_hgt, grep {! /$hit/} @pids;

    There also is a module which implements the part function, which divides one list into two (or more) lists, which would be quite handy here, but I don't find that module at the moment.

      There also is a module which implements the part function...

      see: List::Part

      use List::Part; my ( $in, $out ) = part { m/$hit/ } @pids;

      Where $in is an arrayref to the matches, and $out to the rest.

      It's not at all onerous to implement part doing just one pass, without a module:
      push @{/$hit/ ? \@hits : \@potential_hgt}, $_ for @pids;

      Caution: Contents may have been coded under pressure.
Re: for loop trouble
by ambrus (Abbot) on Aug 12, 2005 at 10:01 UTC

    I guess your problem may be that you put all pids in @potential_hgt whenever it doesn't match an $orth. Is it possible that you wanted to put there only those that don't match any of the @orthologs?

Re: for loop trouble
by graff (Chancellor) on Aug 12, 2005 at 15:23 UTC
    If I understand the task correctly, I think you'll be better off nesting the loops this way (not tested):
    # build the list of targets my @targets = map { /^A(\d+)/; $1 } @orthologs; # go through @pids and segregate them into @hits and @potentials my @hits = my @potentials = (); for my $p ( @pids ) { my $itsahit = 0 for my $t ( @targets ) { if ( $p =~ /$t/ ) { push @hits, $t; $itsahit++; last; } } push @potentials, $p unless ( $itsahit ); }