Perl:对于循环退出条件(last)不能按预期工作

时间:2014-10-29 19:23:36

标签: arrays perl if-statement for-loop

所以我在下面的第二个for循环中遇到了问题。

第一个for循环在ARRAY中找到第一个ATG实例。

第二个for循环应该报告第一个ATG之后的ARRAY中的TAA,TAG或TGA的第一个实例。但它报告了ARRAY中最后一个TAA,TAG或TGA的位置。我不确定为什么退出循环的条件不会阻止这个以及如何解决它。

任何提示都将不胜感激。

my @test_srsrspsp = ( "CCC", "ATG", "ATG", "CGC", "TAA", "TAG" );

sub orf_length {
    #index scalars
    my $rf0_start;
    my $rf0_end;
    #index value counter
    my $i = 0;
    #finds first appearance of ATG in array
    for (@_) {
        $rf0_start = $i if $_ eq 'ATG';
        last if ( defined $rf0_start );
        $i++;
    }
    #only looks for TAG, TAA, or TGA if ATG was found first
    if ( defined $rf0_start ) {
        #reset counter
        $i = 0;
        #is supposed to return the index value of the first appearance of TAG, TAA, or TGA
        #that has an index value larger than that of ATGs but instead returns the index value
        #of the last TAA, TAG, or TGA
        for (@_) {
            $rf0_end = $i if $_ =~ /TA(G|A)|TGA/;
            if ( ( defined $rf0_end ) > $rf0_start ) {
                last;
            }
            $i++;
        }
    }
    #reports positions of found values and the number length of the sequence between them
    if ( defined( $rf0_end and $rf0_start ) ) {
        my $length = ( $rf0_end - $rf0_start + 1 ) * 3;
        print "Start Codon after pos: $rf0_start \n";
        print "End Codon at pos: $rf0_end \n";
        print "First ORF of \n@_ \nhas length: $length \n";
    } else {
        print "No ORF found in @_\n";
    }

}

我也试过使用不同版本的for循环但没有成功。

for (@_) {
    $rf0_end = $i if $_ =~ /TA(G|A)|TGA/;
    last if ( ( defined $rf0_end ) > $rf0_start );
    $i++;
}

2 个答案:

答案 0 :(得分:0)

第二个循环中的问题是 if ( ( defined $rf0_end ) > $rf0_start ) 。它将布尔值与整数值进行比较。要正常工作,可以用

替换

工作语法: if ( ( defined $rf0_end ) && ($rf0_end > $rf0_start) )

答案 1 :(得分:0)

你也遇到了

行的问题
if ( defined( $rf0_end and $rf0_start ) ) {

需要

if ( defined $rf0_end and defined $rf0_start ) {

虽然,在这种情况下,

if ( defined $rf0_end ) {

会很好,因为$rf0_end只有在定义了$rf0_start时才会定义。

我更愿意使用firstidx中的List::MoreUtils函数执行此操作,如下所示,尽管您可能需要安装模块,因为它目前不在核心中。< / p>

use strict;
use warnings;

use List::MoreUtils 'firstidx';

my @test_srsrspsp = qw/ CCC ATG ATG CGC TAA TAG /;

orf_length(@test_srsrspsp);

sub orf_length {

    my ($rf0_start, $rf0_end, $rf0_len);

    $rf0_start = firstidx { /ATG/ } @_;
    if (defined $rf0_start) {
        my $offset = $rf0_start + 1;
        $rf0_end = $offset + firstidx { /TA[GA]|TGA/ } @_[$offset .. $#_];
    }

    if (defined $rf0_end) {
        my $rf0_len = ($rf0_end - $rf0_start + 1) * 3;
        print "Start Codon after pos: $rf0_start \n";
        print "End Codon at pos: $rf0_end \n";
        print "First ORF of\n@_\nhas length: $rf0_len\n";
    }
    else {
        print "No ORF found in @_\n";
    }
}

<强>输出

Start Codon after pos: 1 
End Codon at pos: 4 
First ORF of 
CCC ATG ATG CGC TAA TAG 
has length: 12 

<强>更新

如果您想避开模块,可以这样写。功能相同。

sub orf_length {

   my ($rf0_start, $rf0_end, $rf0_len);

    my $i = 0;
    for (@_) {
        if (not defined $rf0_start) {
            $rf0_start = $i if /ATG/;
        }
        elsif (/TA[GA]|TGA/) {
            $rf0_end = $i;
            last;
        }
        ++$i;
    }

    if (defined $rf0_end) {
        my $rf0_len = ($rf0_end - $rf0_start + 1) * 3;
        print "Start Codon after pos: $rf0_start \n";
        print "End Codon at pos: $rf0_end \n";
        print "First ORF of\n@_\nhas length: $rf0_len\n";
    }
    else {
        print "No ORF found in @_\n";
    }
}