如何确定给定值落入哪个范围?

时间:2011-08-24 00:30:36

标签: perl bioinformatics bioperl

我有两个数据集:'数据1'和'数据2'。你能帮我找一下'数据1'中posi的每个值,'数据2'中的位置,其中posi位于Star_posi和end_posi之间。

数据1

  Num     posi 
   1        2 
   2        14
   3        18
   4        19
  ...      ...

数据2

 Num      Star_posi    End_posi
  1          1            10
  2          3            15
  3          17           21
  4          23           34
 ...       ...           ...

输出

  1. star_posi 1和end_posi 10之间的数据2中包含的第2位数据1。
  2. star_posi 3和end_posi 15之间的数据2中包含的第14位数据1。
  3. 我想识别数据2中的行,其中数据1中的值包含在数据2中的行的范围内。我在下面创建了脚本,但是我没有达到目标。

       #!/usr/bin/perl -w
       use strict;
       use warnings;
       use Data:ump qw(dump);
    
       #Sort the position**************
    
       my (@posi1, $Num2, @Num2, @Num1);
       open(POS1,"<posi.txt");
       @posi1=<POS1>;
       @Num1=@posi1;
       open(LIST,">list.txt"); {
       @Num2= sort {$a <=> $b} @Num1;
       $Num2 = join( '', @Num2);
       print $Num2;
       print LIST $Num2."\n";
       }
       close(LIST); 
    

    如果你能给出一些指示,我将不胜感激。

2 个答案:

答案 0 :(得分:3)

你的代码很乱。此外,它不会以任何方式解决您的问题。

您要做的是split来自while循环中文件的行,并将它们存储在散列中。获得这些值后,您可以轻松地将它们与<>运算符进行比较,以查看它们落入的范围。

use strict;
use warnings;
use autodie;

my (%data1,%data2);


open my $in, '<', 'data1.txt';
while (<$in>) {
    next unless /^\s*\d/;
    my ($num, $posi) = split;
    $data1{$num} = $posi;
}

open $in, '<', 'data2.txt';
while (<$in>) {
    next unless /^\s*\d/;
    my ($num, $star, $end) = split;
    $data2{$num}{'star'} = $star;
    $data2{$num}{'end'}  = $end;
}
close $in;

请注意,我正在跳过(next)任何不以数字开头的行,例如标题和空行以及我们在数据中不需要的其他内容。

现在,您将拥有哈希值,并可以执行您需要的测试。例如:

for my $num (keys %data1) {
    my $val = $data1{$num};
    for my $num2 (keys %data2) {
        my $min = $data2{$num2}{'star'};
        my $max = $data2{$num2}{'end'};
        if ( ($val > $min) and ($val < $max) ) {
            print "Data 1 at posi $val contained in Data 2 between star_posi $min and end_posi $max.\n";
            last;
        }
    }
}
祝你好运!

答案 1 :(得分:2)

您应该查看名为Tie::RangeHash的CPAN模块,该模块用于完全此类问题。

use Tie::RangeHash;
my $hour_name = new Tie::RangeHash Type => Tie::RangeHash::TYPE_NUMBER;

$hour_name->add(' 0, 5', 'EARLY');
$hour_name->add(' 6,11', 'MORNING');
$hour_name->add('12,17', 'AFTERNOON');
$hour_name->add('18,23', 'EVENING');

# and in a loop elsewhere...
my $name = $hour_name->fetch($hour) || "UNKNOWN";