I have two sets of ranges. Each range is a pair of integers (start and end) representing some sub-range of a single larger range. I need to determine which ranges from set A overlap with which ranges from set B.
问问题
198 次
1 回答
3
我认为您的输入被截断了,因为我看不到任何方法可以获取您预期输出的最后一行。
但是,对于那里的部分,我认为您需要这样的脚本:
my %cover;
foreach my $line ( <STDIN> )
{
chomp $line;
my ( $tag, $lo, $hi ) = split /\s+/, $line;
map { $cover{$_}++ } ($lo .. $hi);
}
my $beg = 0;
my $end = 0;
my $cnt = 0;
foreach my $val ( sort { $a <=> $b } keys %cover )
{
if ($cover{$val} != $cnt || $val > $end + 1)
{
if ($cnt > 0)
{
print "chr1\t$beg\t$end\t$cnt\n";
}
$cnt = $cover{$val};
$beg = $val;
$end = $val;
} else
{
$end = $val;
}
}
if ($cnt > 0)
{
print "chr1\t$beg\t$end\t$cnt\n";
}
但是,您没有告诉我们如何处理chr1
或如何在输入和输出之间关联它(例如,那里可能出现其他值吗?)所以我只是在输出中硬编码了它。您必须适当地更改该部分。
此外,我的脚本输出的范围与您的“预期输出”略有不同,特别是在两个范围相邻的地方。例如,我的脚本输出
chr1 556 579 1
chr1 580 592 2
但是您的预期输出给出580
而不是579
第一行。我不确定您的预期输出是否正确。如果你真的想要 580 那里(这没有多大意义),那么你可以修改上面的脚本以输出$end+1
when $val == $end+1
。但这似乎很奇怪。
这是代码的修改版本,当范围邻接时会出现奇怪的行为:
my %cover;
foreach my $line ( <STDIN> )
{
chomp $line;
my ( $tag, $lo, $hi ) = split /\s+/, $line;
map { $cover{$_}++ } ($lo .. $hi);
}
my $beg = 0;
my $end = 0;
my $cnt = 0;
foreach my $val ( sort { $a <=> $b } keys %cover )
{
if ($cover{$val} != $cnt || $val > $end + 1)
{
## unusual value for '$end' when ranges abut.
$end = $val if ($val == $end + 1);
if ($cnt > 0)
{
print "chr1\t$beg\t$end\t$cnt\n";
}
$cnt = $cover{$val};
$beg = $val;
$end = $val;
} else
{
$end = $val;
}
}
if ($cnt > 0)
{
print "chr1\t$beg\t$end\t$cnt\n";
}
于 2013-11-03T18:52:08.390 回答