我有舍入错误吗?Perl的

ES5*_*S55 2 arrays perl loops rounding nested-loops

我的脚本应该做以下.它需要一个旧的标量列表,并创建一个新的,相应的数字列表.旧列表称为@oldMarkers,新列表称为@newMarkers.

示例输入如下: chr1, chr2, IMP, chr3, IMP, IMP, IMP, chr4

示例输出如下: 1, 2, 2.1, 3, 3.1, 3.2, 3.3, 4

脚本的要点是读取@oldMarkers列表并输出一个列表,其中对于包含字母"chr"的元素的每个实例,一个整数被推入数组@newMarkers.对于@oldMarkers中IMP的每个实例,都会向@newMarkers添加一个十进制数.新的十进制数与前面的数字具有相同的"基本整数",但添加了.1.换句话说,"IMP"的多个后续实例应该具有与最近读取的"chr"条目相同的整数,其上加上小数值,计算与最近"chr"对应的IMP的数量.条目.

下面的脚本几乎100%工作.它甚至通常在以下实例中工作.在@oldMarkers的一些地方,IMP有很多条目.当一行中有超过10个IMP时,代码应该将值推送到@newMarkers,以便该条目块的所有"IMP"具有相同的整数,这也与最近对应的数字相匹配.在@oldMarkers中读取"chr"的实例.对于整数,添加0.1.当小数的值达到.9时,小数"重新开始"回到.1并从那里上升,直到IMP条目的延伸结束.

例如,如果@oldMarkers有一个13"IMP"的块,并且是: chr1, chr2, IMP, IMP, IMP, IMP, IMP, IMP, IMP, IMP, IMP, IMP, IMP, IMP, IMP, chr2

然后@newMarkers应该是: 1, 2, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 2.1, 2.2, 2.3, 2.4, 3

脚本摘要:

原始文件包含多行两个元素.第一个元素并不重要,因此在代码中跳过了.每行的第二个元素是一个ID,可以是"chr4"或"IMP".甲while循环读取每一行,将第二元件到阵列@oldMarkers.

然后,按条目读取此数组.该脚本首先询问@newMarkers中的条目是否与原始@oldMarker列表中的"chr"或"IMP"相对应.这是通过第一个if和第一个完成的else.

接下来,对于这两个条件,进一步询问该条目是否跟随对应于"chr"或"IMP"条目的数字本身.这是通过在第一个这样的集合中嵌入ifelse设置来完成的.

然后定义新元素并将其推送到@newMarker,具体取决于条件.

就像我说的,这主要是有效的.但是,有时,当IMP的延伸超过10时,脚本不会"回收"小数.相反,它将.1添加到前一个值并输入一个新的整数整数.但对于超过10的其他延伸,它工作正常.它与这个"错误"不一致.

你能发现问题吗?

my @oldMarkers = ();
my @newMarkers = ();

while ( my $line = <$FILE> )
    {
    chomp $line;
    my @entries = split( '\t', $line );
    push( @oldMarkers, $entries[ 1 ] ); 
    } ### end of while


for ( my $i = 0 ; $i < scalar @oldMarkers   ; $i++ )
    {  
     if ( $oldMarkers[ $i ] =~ m/chr/ ) ### is a marker
        {
         if ( $oldMarkers[ $i - 1 ] =~ m/IMP/ ) ### new marker comes after imputed site
            {
             push( @newMarkers, int( $newMarkers[ $i - 1 ] ) + 1 );            
            }

       else  ### is coming after a marker                                       
           {
            push( @newMarkers, $newMarkers[ $i - 1 ] + 1 ); 
           }    

      } ### if

   else    ### is an imputed site
      {
       if ( $oldMarkers[ $i - 1 ] =~ m/IMP/ ) ### imputed site is after another imputed site
          {
           my $value = $newMarkers[ $i - 1 ] - int( $newMarkers[ $i - 1 ] );

           if ( $value < .9 )
                {
                 push( @newMarkers, $newMarkers[ $i - 1 ] + .1 );   
                }

          elsif ( $value > .9 )
                {
                 push( @newMarkers, int( $newMarkers[ $i - 1 ] ) + .1  );   
                } 


        } ### if

   else ### imputed site is after a marker
        {
         push( @newMarkers, int( $newMarkers[ $i - 1 ] ) + .1 ); 
        }    

    } ### else   

} ### for    


print $newMarkerfile join( "\t", @newMarkers);             
Run Code Online (Sandbox Code Playgroud)

Ilm*_*nen 6

仅使用整数运算来完成此操作会更容易,更可靠.基本上,跟踪两个整数值:一个用于前面.的数字,一个用于后面的数字.如果.达到10 后的数字,将其重置为1:

my @newMarkers;
my $chrCount = 0;
my $impCount = 0;

foreach my $marker (@oldMarkers) {
    if ( $marker =~ /^chr\d+$/ ) {
        $chrCount++;
        $impCount = 0;
        push @newMarkers, $chrCount;
    } elsif ( $marker eq "IMP" ) {
        $impCount++;
        $impCount = 1 if $impCount == 10;
        push @newMarkers, "$chrCount.$impCount";
    } else {
        die "Unrecognized marker $marker";
    }
}
Run Code Online (Sandbox Code Playgroud)

(在codepad.org上演示)