我有两套范围。每个范围是一对整数(开始和结束),表示单个较大范围的某个子范围。 我需要确定集合A的哪个范围与集合B的范围重叠。
答案 0 :(得分: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
时输出$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";
}