Использование perl-хеша для сравнения столбцов из 2 файлов - PullRequest
1 голос
/ 31 января 2012

Я задал этот вопрос (извините за повторный запрос, на этот раз он другой и сложный), но я много пробовал, но не достиг результатов.

У меня 2 больших файла (с разделителями табуляции).

первый файл ->

Col1           Col2    Col3 Col4     Col5        Col6       Col7    Col8
101_#2          1       H    F0       263        278        2       1.5
102_#1          1       6    F1       766        781        1       1.0
103_#1          2       15   V1       526        581        1       0.0
103_#1          2       9    V2       124        134        1       1.3
104_#1          1       12   V3       137        172        1       1.0
105_#1          1       17   F2       766        771        1       1.0

второй файл ->

Col1    Col2    Col3             Col4
97486   H   262               279
67486   9   118           119
87486   9   183           185
248233  9   124           134

Если значение / символ col3 (файла1) и значение / символ col2 (файла)2) совпадают, а затем сравнивают col5 и col6 файла 1 (например, значение диапазона) с col3 и col4 файла2, если диапазон файла 1 присутствует в файле 2, возвращает эту строку (из файла1), а также добавляет дополнительный столбец1из файла 2 в выводе.

Ожидаемый вывод ->

Col1      Col2    Col3 Col4     Col5        Col6       Col7    Col8   Col9
101_#2        1       H    F0       263        278        2       1.5       97486
103_#1        2       9    V2       124        134        1       1.3       248233 

До сих пор я пробовал что-то с хэшами ->

@ARGV or die "No input file specified";
open my $first, '<',$ARGV[0] or die "Unable to open input file: $!";
open my $second,'<', $ARGV[1] or die "Unable to open input file: $!";
print scalar (<$first>);
while(<$second>){
    chomp;
    @line=split /\s+/;
    $hash{$line[2]}=$line[3];
}
while (<$first>) {
    @cols = split /\s+/;
    $p1 = $cols[4];
    $p2 = $cols[5];
    foreach $key (sort keys %hash){
        if ($p1>= "$key"){
            if ($p2<=$hash{$key})
            {
                print join("\t",@cols),"\n";
            }
        }
        else{ next; }
    }
}

Но нет сравнения col3значение / символ (из файла 1) и значение / символ col2 (из файла 2) в приведенном выше коде.Но это также отнимает много времени и памяти. Кто-нибудь может подсказать, как я могу сделать это быстро, используя хэши или хэши хешей. Большое спасибо.

Привет всем,

Большое спасибо затвоя помощь.Я нашел эффективный способ для моего собственного вопроса.

@ARGV or die "No input file specified";
open $first, '<',$ARGV[0] or die "Unable to open input file: $!";
open $second,'<', $ARGV[1] or die "Unable to open input file: $!";
print scalar (<$first>);


while(<$second>){
chomp;
@line=split /\s+/;

    $hash{$line[1]}{$line[2]}{$line[3]}= $line[0];
    }
while (<$first>) {

    @cols = split /\s+/;

foreach  $key1 (sort keys %hash) {
   foreach $key2 (sort keys %{$hash{$key1}}) {
        foreach  $key3 (sort keys %{$hash{$key1}{$key2}}) {
        if (($cols[2] eq $key1) && ($cols[4]>=$key2) && ($cols[5]<=$key3)){
            print join("\t",@cols),"\t",$hash{$key1}{$key2}{$key3},"\n";

        }   
        last;
    }

}
}
}

Это правильно?

Ответы [ 2 ]

1 голос
/ 31 января 2012

Как насчет использования только awk для этого -

awk '
NR==FNR && NR>1{a[$3]=$0;b[$3]=$5;c[$3]=$6;next} 
($2 in a) && ($3<=b[$2] && $4>=c[$2]) {print a[$2],$1}' file1 file2

Входные данные:

[jaypal:~/Temp] cat file1
Col1           Col2    Col3 Col4     Col5        Col6       Col7    Col8
101_#2          1       H    F0       263        278        2       1.5
109_#2          1       H    F0       263        278        2       1.5
102_#1          1       6    F1       766        781        1       1.0
103_#1          2       15   V1       526        581        1       0.0
103_#1          2       9    V2       124        134        1       1.3
104_#1          1       12   V3       137        172        1       1.0
105_#1          1       17   F2       766        771        1       1.0

[jaypal:~/Temp] cat file2
Col1    Col2    Col3    Col4
97486   H       262     279
67486   9       118     119
87486   9       183     185
248233  9       124     134

Тест:

[jaypal:~/Temp] awk '
NR==FNR && NR>1{a[$3]=$0;b[$3]=$5;c[$3]=$6;next} 
($2 in a) && ($3<=b[$2] && $4>=c[$2]) {print a[$2],$1}' file1 file2
101_#2          1       H    F0       263        278        2       1.5 97486
103_#1          2       9    V2       124        134        1       1.3 248233
1 голос
/ 31 января 2012

Вам не нужны две хеш-таблицы.Вам просто нужна одна хеш-таблица, созданная из записей в первом файле, и когда вы просматриваете второй файл, проверьте, есть ли ключ в хеш-таблице первого файла, используя defined.

Если есть ключ, сравните значения других столбцов (мы сохраняем значения из первого файла в хеш-таблице для ключа третьего столбца).

Если ключа нет, то либо warn, die, либо продолжайте сценарий, ничего не сказав, если вы этого хотите:

#!/usr/bin/perl -w

use strict;
use warnings;

my $firstHashRef;

open FIRST, "< $firstFile" or die "could not open first file...\n";
while (<FIRST>) { 
    chomp $_;
    my @elements = split "\t", $_;
    my $col3Val = $elements[2];  # Perl arrays are zero-indexed
    my $col5Val = $elements[4];
    my $col6Val = $elements[5];

    # keep the fifth and sixth column values on hand, for
    # when we loop through the second file...

    if (! defined $firstHashRef->{$col3Val}) { 
        $firstHashRef->{$col3Val}->{Col5} = $col5Val; 
        $firstHashRef->{$col3Val}->{Col6} = $col6Val; 
    }
}
close FIRST;

open SECOND, "< $secondFile" or die "could not open second file...\n";
while (<SECOND>) {
    chomp $_;
    my @elements = split "\t", $_;
    my $col2ValFromSecondFile = $elements[1];
    my $col3ValFromSecondFile = $elements[2];
    my $col4ValFromSecondFile = $elements[3];

    if (defined $firstHashRef->{$col2ValFromSecondFile}) {
        # we found a matching key
        # 1. Compare $firstHashRef->{$col2ValFromSecondFile}->{Col5} with $col3ValFromSecondFile
        # 2. Compare $firstHashRef->{$col2ValFromSecondFile}->{Col6} with $col4ValFromSecondFile
        # 3. Do something interesting, based on comparison results... (this is left to you to fill in)
    }
    else {
        warn "We did not locate entry in hash table for second file's Col2 value...\n";
    }
}
close SECOND;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...