如何找到范围

时间:2013-11-01 13:26:51

标签: range overlap

我有两套范围。每个范围是一对整数(开始和结束),表示单个较大范围的某个子范围。 我需要确定集合A的哪个范围与集合B的范围重叠。

1 个答案:

答案 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";
}