1

我有两个数据集:“数据 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. 位置 2 的数据 1 包含在 star_posi 1 和 end_posi 10 之间的数据 2 中。
  2. 位置 14 的数据 1 包含在 star_posi 3 和 end_posi 15 之间的数据 2 中。

我想识别数据 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); 

如果您能提供一些指示,我将不胜感激。

4

2 回答 2

3

你的代码是一团糟。此外,它不会以任何方式解决您的问题。

您想要做的是循环split文件中的行,将它们存储在哈希中。while获得这些值后,您可以轻松地将它们与<and>运算符进行比较,以查看它们落在什么范围内。

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;
        }
    }
}

祝你好运!

于 2011-08-24T01:06:52.437 回答
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";
于 2011-08-24T07:36:02.920 回答