简体   繁体   English

Perl:对于循环退出条件(最后)未按预期工作

[英]Perl: For loop exit condition (last) not working as expected

so I'm having an issue with my second for loop below. 所以我下面的第二个for循环有问题。

The first for loop finds the first instance of ATG in the ARRAY. 第一个for循环在ARRAY中找到ATG的第一个实例。

The second for loop is supposed to report the first instance of TAA, TAG, or TGA in the ARRAY that is after the first ATG. 第二个for循环应该报告第一个ATG之后的ARRAY中的TAA,TAG或TGA的第一个实例。 But instead it reports the position of the last TAA, TAG, or TGA in the ARRAY. 但是,它会报告阵列中最后一个TAA,TAG或TGA的位置。 I'm not sure why my condition for exiting the loop is not preventing this nor how to fix it. 我不确定为什么退出循环的条件既不能防止这种情况,也不能解决问题。

Any tips would be appreciated. 任何提示将不胜感激。

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";
    }

}

I've also tried using a different version of the for loop with no success. 我也尝试过使用其他版本的for循环,但没有成功。

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

Issue is if ( ( defined $rf0_end ) > $rf0_start ) in the second loop. 问题是if ( ( defined $rf0_end ) > $rf0_start )在第二个循环中if ( ( defined $rf0_end ) > $rf0_start ) It compares a boolean with integer value. 它将布尔值与整数值进行比较。 To work properly it can be replaced with 为了正常工作,可以将其替换为

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

You also have a problem with the line 你也有问题

if ( defined( $rf0_end and $rf0_start ) ) {

which needs to be 需要

if ( defined $rf0_end and defined $rf0_start ) {

although, in this case, 尽管在这种情况下

if ( defined $rf0_end ) {

will do fine, as $rf0_end gets defined only if $rf0_start is defined. 会做得很好,因为$rf0_end如果只获取定义$rf0_start定义。

I would prefer to use the firstidx function from List::MoreUtils to do this, as shown below, although you may need to install the module as it isn't in core at present. 我宁愿使用List::MoreUtilsfirstidx函数来执行此操作,如下所示,尽管您可能需要安装模块,因为它目前不在核心中。

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";
    }
}

output 输出

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

Update 更新资料

If you prefer to avoid the module, you could write it this way. 如果您不想使用该模块,则可以用这种方式编写。 The functionality is identical. 功能是相同的。

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";
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM