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"条目的数字本身.这是通过在第一个这样的集合中嵌入if和else设置来完成的.
然后定义新元素并将其推送到@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)
仅使用整数运算来完成此操作会更容易,更可靠.基本上,跟踪两个整数值:一个用于前面.的数字,一个用于后面的数字.如果.达到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)