我遇到了一个相当独特的问题。我有 2 个正在阅读的文件。这 2 个文件的小版本如下所示:
文件 1
chr1 9873 12227 11873 2354 + NR_046018 DDX11L1
chr1 760970 763155 762970 2185 + NR_047520 LOC643837
文件2
chr1 9871 0
chr1 9872 1
chr1 9873 1
chr1 9874 2
chr1 9875 1
chr1 9876 3
chr1 9877 3
chr1 760970 1
chr1 760971 1
chr1 760972 1
chr1 760973 2
chr1 760974 3
chr1 760975 3
chr1 760976 4
chr1 760977 5
chr1 760978 6
chr1 760979 7
chr1 760980 6
chr1 760981 7
chr1 760982 8
chr1 760983 9
chr1 760984 10
chr1 760985 11
chr1 760986 12
chr1 760987 10
chr1 760988 9
chr1 760989 6
问题
从第一个文件中,我必须从每一行中提取第二个元素并将其作为
$start
. 结束位置由 确定$end = $start + 10
。基于
$start
,我现在必须获取第二个文件,并查看每行的第二个元素。找到$start
后,我需要将 5 个一组的第三个元素的下 5 个对应值相加,最多为$end
.
因此,我以 5 个为一组进行求和,将获得 2 个求和值 $end
。$start + 10
如果某些值 upto$end
不存在于第二个文件的第二个元素中,代码不应停止,它应继续执行求和并将总和显示为 0(如果不存在连续的 5 个元素组)。
以此处的文件为例,来自File1,第二个元素 = 9873
,它被分配给$start
. 因此$end
将是$start+10
9883。
从File2中,一旦$start
在该行的第 2 个元素中找到,接下来 5 行的第 3 个元素必须作为 1 组求和,接下来的 5 个值作为第 2 组求和直到$end
。
笔记
这里可以在File2中看到,$end
即 9883 不存在。因此,从 9879 到 9883 的值的总和必须是zero
。它不能将 760970 的值相加......
期望的输出
chr1 9873 12227 11873 2354 + NR_046018 DDX11L1 10 0
chr1 760970 763155 762970 2185 + NR_047520 LOC643837 8 25
注意事项
- 在处理实际文件时, $end = $start+10,000(而不是 $end = $start+10 )
- 此外,在同一个注释中,将对 25 个值的组求和(而不是 5 个),在处理实际文件时总共获得 400 个值。
- 如果 $file2 的第二个元素中不存在一系列值,则求和应正常进行,如果不存在连续的 25 个值对,
0
则应打印输出。 - 每个文件包含 > 100 万行。
代码
到目前为止,我编写的代码能够做到以下几点:
- 从文件中读取。
- 分配
$start
和$end
来自file1 - 从file2,将所有第二个元素推入 array
@c_posn
;所有第三个元素到数组@peak
中。 - 检查是否
$start
存在于@c_posn
我无法弄清楚如何进行求和部分。我曾想过创建一个哈希,其中 2nd 文件的所有 2nd 元素进入keys和 3rd 元素进入values。但是哈希是无序的。@c_posn
所以我为第二个元素@peaks
和第三个元素创建了 2 个数组。但现在我不知道如何同时比较 2 个数组(以确保 760970 的值不会相加)
use 5.012;
use warnings;
use List::Util qw/first/;
my $file1 = 'chr1trialS.out';
my $file2 = 'b1.wig';
open my $fh1,'<',$file1 or die qw /Can't_open_file_$file1/;
open my $fh2,'<',$file2 or die qw /Can't_open_file_$file2/;
my($start, $end);
while(<$fh1>){
my @val1 = split;
$start = $val1[1]; #Assign start value
$end = $start + 10; #Assign end value
say $start,"->",$end; #Can be commented out
}
my @c_posn;
my @peak;
while(<$fh2>){
my @val2 = split;
push @c_posn,$val2[1]; #Push all 2nd elements
push @peak, $val2[2]; #Push all 3rd elements
}
if (first { $_ eq $start} @c_posn) { say "I found it! " } #To check if $start is present in @c_posn
say "@c_posn"; #just to check all 2nd elements are obtained
say "@peak"; #just to check all 3rd elements are obtained
感谢您花时间解决我的问题。如果需要任何澄清,请务必问我。我将不胜感激任何评论/回答。