如何在perl范围内检查范围内的范围?

时间:2017-02-16 01:01:01

标签: perl range

我想检查其他范围的范围。例如:

待检查:

   check1: 10-50
   check2: 100-150
   check3: 500-600

要检查的地方:

   range1: 49-100
   range2: 800-900

我想检查check1中的每个数字是否存在于range1或range2中,依此类推。如果存在任何数字,则打印范围。对于这里:check1中有50个存在于range1中。 100是check2存在于range1中。但是检查3在range1或range2中都不存在。如何实现这一目标?

我从4列中的数据开始:

#!/usr/bin/perl
use warnings;
use strict;
use v5.16;


my (@check1, @check2, @range1, @range2);

my $header = <DATA>;
foreach (<DATA>){
    chomp $_;
    my @columns = split "\t", $_;



    #check (check1 to check2) in range (all range1 to range2) both inclusive
    #check 3631 5899 in all range1 to range2, if found print YES
    #check 3760 5630 in all range1 to range2, if found print YES

}

__DATA__
#check1 check2  range1  range2
3631    5899    4706    5095
3760    5630    5174    5326
3631    3913    7834    8989

1 个答案:

答案 0 :(得分:-1)

以下是我将如何处理这个问题:

my @checks = (
        [qw(check1 10 50)],
        [qw(check2 100 150)],
        [qw(check3 500 600)]);

while (my $line = <DATA>) {
    my ($name, $min_r, $max_r) = split (' ', $line);
    print $name;
    foreach my $check (@checks) {
        print " $check->[0]" if overlap($min_r, $max_r, $check->[1], $check->[2]);
    }
    print "\n";
}

sub overlap {
    my ($r1, $r2, $c1, $c2) = @_;
    return 1 if $r1 >= $c1 && $r1 <= $c2;
    return 1 if $r2 >= $c1 && $r2 <= $c2;
    return 1 if $r1 < $c1 && $r2 > $c2;
    return 0;
}

__DATA__
range1 49 100
range2 800 900

编辑: 看来你不喜欢我的回答。这是另一个使用奇怪的4列数据格式的命题(我不明白为什么你会有相同数量的检查和范围)并且如你在一个答案中所说的那样颠倒检查和范围的作用。如果检查存在于其中一个范围内,则打印YES。如果你想要一个YES,如果所有范围都有检查,你只需要添加2个否定:

my @checks;
my @ranges;
my $header = <DATA>;
while (my $line = <DATA>) {
    my ($min_c, $max_c, $min_r, $max_r) = split (' ', $line);
    push @checks, [$min_c, $max_c];
    push @ranges, [$min_r, $max_r];
}

foreach my $check (@checks) {
    print "$check->[0] $check->[1] YES\n"
        if grep {overlap($check->[0], $check->[1], $_->[0], $_->[1])} @ranges;
}

__DATA__
#check1 check2  range1  range2
3631    5899    4706    5095
3760    5630    5174    5326
3631    3913    7834    8989