Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

looping foreach error

by Anonymous Monk
on Jun 24, 2014 at 13:43 UTC ( #1091054=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dearest Monks, I have been playing around with the same code for over a day and I still don't understand where I'm falling down. I'm trying to pull out a certain sequence based on certain conditions and then print to a file the results. Unfortunately, what ends up printing to file is multiple matches of the same sequence. I have done a few tests and have commented out what happens when I print out the sequence at different stages in my code. I have tried googling,using books,pure determination, and I'm still confused... Please can you help?

my ($value, $col, $col2, $l_o_b, $left, $matchedID, $diff_three_prime, + $diff_five_prime, $sequence); open (EXONS_five, '>fasta_exons_five'); open (EXONS_three, '>fasta_exons_three'); my $i = 0; foreach my $match(@exonic_matches) { $value = $exon_ID[$i]; $col = $exon_left{$value}; $col2 = $exon_right{$value}; my @three_prime_ss = split(",", $col); my @five_prime_ss = split(",", $col2); my @reverse_three = reverse(@three_prime_ss); my @reverse_five = reverse(@five_prime_ss); if ($strands{$value} =~ m/\+/) { $diff_three_prime = $LBP[$i] - $three_prime_ss[$exons2{$value} - 1 +]; $diff_five_prime = $LBP[$i] - $five_prime_ss[$exons2{$value} - 1]; + $matchedID = $ID{$LBP[$i]}; if ($diff_three_prime !~ m/\-/ && $diff_three_prime <= 3) { $BP{$LBP[$i]} =~ s/\[[ACTG]\]/$alt[$i]/i; $l_o_b = 20; ##$right_of_boundary = 3; $l_o_b = $l_o_b + $diff_three_prime; $left = 51 - $l_o_b; $sequence = substr($BP{$LBP[$i]}, $left, 23); ## print $sequence, "\n"; ## POINT ONE: prints out correct sequence for condition ## } elsif ($diff_five_prime =~ m/\-/ && $diff_five_prime >= -3) { $BP{$LBP[$i]} =~ s/\[[ACTG]\]/$alt[$i]/i; $l_o_b = 3; ##$right_of_boundary = 6; $l_o_b = $l_o_b + $diff_five_prime; $left = 51 - $l_o_b; $sequence = substr( $BP{$LBP[$i]}, $left, 9); ## print $sequence, "\n"; ## POINT TWO: prints out what I want for this condition plus some repe +ats ## } } ## print $sequence, "\n"; ## POINT THREE: prints out multiple sequences of the above ## my $seq_length = length($sequence); if ($seq_length == 9) { print EXONS_five (">" . "$match_exon{$matchedID}" . "\n", lc($sequ +ence),"\n"); } else { print EXONS_three (">" . "$match_exon{$matchedID}" . "\n", lc($seq +uence),"\n"); } $i++; } close (EXONS_five); close (EXONS_three);

Replies are listed 'Best First'.
Re: looping foreach error
by tangent (Vicar) on Jun 24, 2014 at 13:57 UTC
    You declare "$sequence" outside of the foreach loop so if there are no matches within a loop it will print out the match from the previous loop. Try resetting $sequence at the start of the loop:
    foreach my $match(@exonic_matches) { $sequence = ''; # ...
Re: looping foreach error
by InfiniteSilence (Curate) on Jun 24, 2014 at 13:59 UTC

    This code is missing stuff...what are the contents of @exonic_matches?

    Celebrate Intellectual Diversity

Re: looping foreach error
by Laurent_R (Canon) on Jun 24, 2014 at 20:49 UTC
    I am sorry if this is slightly off-topic (not really though, but I admit it does not really answer your original question), but I do not wish to read and try to understand code that is so poorly formatted. Even though the compiler does not care about it, indenting properly is not an option, it is a necessity, it is of the essence of programming.

    Assuming I was asking job candidates to write a short Perl program in order to rate their capacity, I would simply not hire somebody producing such code, even if the program result was correct, because this is just far too sloppy (I am sorry, don't take this a personal critique, but really as an advice and opportunity to improve). Now, the reality is that we are not doing Perl tests for new candidates, because we don't care that much if they know Perl; we use many technologies, Perl is just one of them, and they will have to learn it eventually. But the point is that I would not hire anyone writing such poorly formatted code in any programming language. In other words, to me, writing clean code is in my view a much more important asset than any specific language skills.

    Using correct and consistent indentation (irrespective of various coding styles among which you might pick one or the other) is one of the keys to understand what you write, to make it understandable to the coworkers that will have to maintain your code and also to explaining your intentions to the reader (this is essential: if I know, through formatting, what you mean, then I have a fair chance to find a possible bug; if I do not even know what you intended to do, then there is a significant chance that I'll be lost). If you have to, use a code prettifier such as Perl::Tidy or perltidy, but I would encourage you to write tidy code in the first place, because it greatly helps you to better think your code.

    Just a couple examples to explain. You have:

    my $i = 0; foreach my $match(@exonic_matches) { $value = $exon_ID[$i]; $col = $exon_left{$value}; #...
    Everything that is within the opening brace at the end of the first line should be indented. In addition, although this is less important, if you want to insert vertical spaces, put them before the foreach line, not after. So this could be:
    my $i = 0; foreach my $match(@exonic_matches) { $value = $exon_ID[$i]; $col = $exon_left{$value}; #... }
    or possibly:
    my $i = 0; foreach my $match(@exonic_matches) { $value = $exon_ID[$i]; $col = $exon_left{$value}; #... }
    depending on your preferred style.

    Similarly, your code:

    if ($strands{$value} =~ m/\+/) { $diff_three_prime = $LBP[$i] - $three_prime_ss[$exons2{$value} - 1 +]; $diff_five_prime = $LBP[$i] - $five_prime_ss[$exons2{$value} - 1]; + # ...
    would be much better rewritten this way:
    if ($strands{$value} =~ m/\+/) { $diff_three_prime = $LBP[$i] - $three_prime_ss[$exons2{$value} + - 1]; $diff_five_prime = $LBP[$i] - $five_prime_ss[$exons2{$value} - + 1]; # ...
    Just to state it once more, this is not a matter of taste, this is essential to good programming. I do not really care which formatting style you choose (K&R, GNU, Microsoft, ...), but the formatting has to be consistent and to show the structure of your program.

    And, again, I am really not writing this to chastise you in any way, but to try to help you using better programming practices. Really do it, I am sure that you will see the benefits fairly quickly.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1091054]
Approved by Corion
Front-paged by toolic
Discipulus added his 2 neurocents to windwos perl suggestions issue

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (6)
As of 2018-06-25 09:50 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (126 votes). Check out past polls.