比较两个文件和一列中的列应该在-3到+3之间的范围内,使用perl给出两个文件的并集

时间:2013-01-22 15:38:22

标签: perl

我想比较两个文件中的三列,第三列可以在-3到+3之间的范围内,给我两个文件的联合。 档案1

miR156a AT1G27360   1253
miR156a AT1G27370   2368
miR156a AT1G53160   586

文件2

miR156a AT1G27360   1252    
miR156a AT1G27370   2367    
miR156a AT1G53160   123 
miR156a AT1G69170   1296

预期输出

miR156a AT1G27360   1253
miR156a AT1G27370   2368
miR156a AT1G53160   586
miR156a AT1G53160   123 
miR156a AT1G69170   1296

我曾尝试编写一个perl脚本,在其中我只能找到交叉点,但无法获得两个文件的并集

open(FH1, "$filename1");
open(FH2, "$filename2");
while ( $line1 = <FH1> ) {
    chomp $line1;
    @temp = split(/\s+/, $line1);
    if ($#temp > 1) {
        push(@miR_TP, $temp[0]);
        push(@tar_TP, $temp[1]); 
        push(@start_TP, $temp[2]); 
    }
}
while ( $line2 = <FH2> ) {
    chomp $line2;
    @temp2 = split(/\s+/, $line2);
    if($#temp > 1) {
        push(@miR, $temp2[0]);
        push(@tar, $temp2[1]); 
        push(@start, $temp2[2]);        
    }
}
for ($i=0 ; $i<=$#miR ; $i++) {
    for($j=0 ; $j<=$#miR_TP ; $j++) {
        if (    ($miR[$i] eq $miR_TP[$j]) && 
            ($tar[$i] eq $tar_TP[$j]) &&
            (
                ($start[$i] eq $start_TP[$j])    ||
                ($start[$i] eq  $start_TP[$j]+1) ||
                ($start[$i] eq  $start_TP[$j]+2) ||
                ($start[$i] eq  $start_TP[$j]+3) ||
                ($start[$i] eq  $start_TP[$j]-1) ||
                ($start[$i] eq  $start_TP[$j]-2) ||
                ($start[$i] eq  $start_TP[$j]-3)
            )) {
            print "$miR[$i]\t$tar[$i]\t$start[$i]\n";
        }
    }
}

请帮我修改代码。

1 个答案:

答案 0 :(得分:3)

使用散列而不是数组。而不是复杂的条件,使用abs函数:

#!/usr/bin/perl
use warnings;
use strict;

my $filename1 = 'file1';
my $filename2 = 'file2';

my %hash;

open my $FH, '<', $filename1 or die $!;

while (my $line = <$FH>)
{
    chomp $line;
    my ($mir, $tar, $start) = split ' ', $line;
    if (defined $start)
    {
        print $line, "\n";                   # Always show file 1.
        push @{ $hash{$mir}{$tar} }, $start;
    }
}

open $FH, '<', $filename2 or die $!;
while (my $line = <$FH>)
{
    chomp $line;
    my ($mir, $tar, $start) = split ' ', $line;
    unless (exists $hash{$mir}
            and exists $hash{$mir}{$tar}
            and grep 3 >= abs $start - $_, @{ $hash{$mir}{$tar} })
    {
              print $line, "\n";
    }
}