2014-07-27 18 views
-1

我试图打印@ arr3范围内的值,它们位于@ arr4(不包括在arr4的范围内)范围之外,但我没有得到所需的输出。请建议我在下面的代码修改,以获得输出1,2,8,13(不重复的值如果有的话)如何匹配超出范围的数字

文件1:导致

1..5 
5..10 
10..15 

文件2:注释

3..7 
9..12 
14..17 

代码:

#!/usr/bin/perl 

open($inp1, "<result")  or die "not found"; 
open($inp2, "<annotation") or die "not found"; 

my @arr3 = <$inp1>; 
my @arr4 = <$inp2>; 

foreach my $line1 (@arr4) { 
    foreach my $line2 (@arr3) { 

    my ($from1, $to1) = split(/\.\./, $line1); 
    my ($from2, $to2) = split(/\.\./, $line2); 

    for (my $i = $from1 ; $i <= $to1 ; $i++) { 
     for (my $j = $from2 ; $j <= $to2 ; $j++) { 

     $res = grep(/$i/, @result); #to avoid repetition 

     if ($i != $j && $res == 0) { 

      print "$i \n"; 

      push(@result, $i); 
     } 
     } 
    } 
    } 
} 

回答

1

试试这个:

#!/usr/bin/perl 
use strict; 
open (my $inp1,"<result.txt") or die "not found"; 
open (my $inp2,"<annotation.txt") or die "not found"; 

my @result; 
my @annotation; 

foreach my $line2 (<$inp2>) { 
    my ($from2,$to2)=split(/\.\./,$line2); 
    @annotation = (@annotation, $from2..$to2); 
} 
print join(",",@annotation),"\n"; 
my %in_range = map {$_=> 1} @annotation; 

foreach my $line1 (<$inp1>) { 
    my ($from1,$to1)=split(/\.\./,$line1); 
    @result = (@result, $from1..$to1); 
} 

print join(",",@result),"\n"; 
my %tmp_hash = map {$_=> 1} @result; 
my @unique = sort {$a <=> $b} keys %tmp_hash; 
print join(",",@unique),"\n"; 

my @out_of_range = grep {!$in_range{$_}} @unique; 
print join(",",@out_of_range),"\n"; 

print语句当然是临时性的,当然,当你运行这个语句时,这些语句是帮助显示发生了什么的。其基本思想是使用一个散列来消除“结果”中的重复数字,并使用另一个散列来指示哪些数字在“注释”中。

如果您使用了模式匹配而不是split,那么我认为这会让忽略额外的不是数字范围的输入行更容易一些,以防您输入的文件只有一些额外的“你需要跳过的行。

1

如果文件的内容在您的控制之下,您可以使用eval来解析它们。另一方面,如果可能还有别的东西不符合你的要求,那么使用下面的内容会很危险。

#!/usr/bin/perl 

use strict; 
use warnings; 
use autodie; 
use Data::Dumper; 

open my $inc, '<', 'result'; 
open my $exc, '<', 'annotation'; 

my (%include, %exclude, @result); 
while (<$inc>) { $include{$_} = 1 for eval $_ } 
while (<$exc>) { $exclude{$_} = 1 for eval $_ } 

for (sort {$a <=> $b} keys %include) { 
    push @result, $_ unless $exclude{$_} 
} 
print Dumper \@result; 

返回:

$VAR1 = [ 1, 2, 8, 13 ]; 
0

你唯一需要的主要工具是在perlfaq4 - How can I remove duplicate elements from a list or array?

代表以下打开文件句柄到字符串引用,但很明显,这些可以替换为一个%seen风格哈希相应的文件名:

use strict; 
use warnings; 
use autodie; 

my %seen; 

open my $fh_fltr, '<', \ "3..7\n9..12\n14..17\n"; 
while (<$fh_fltr>) { 
    my ($from, $to) = split /\.{2}/; 
    $seen{$_}++ for $from .. $to; 
} 

my @result; 

open my $fh_src, '<', \ "1..5\n5..10\n10..15\n"; 
while (<$fh_src>) { 
    my ($from, $to) = split /\.{2}/; 
    push @result, $_ for grep {!$seen{$_}++} $from .. $to; 
} 

print "@result\n"; 

输出:

1 2 8 13