2014-01-25 5 views
0

У меня есть два «разных» файлов с одного типа данных, т.е.Perl Hash Сравнение

KEY_gl Start_gl End_gl 
    1 114029 17 
    2 284 1624 
    3 1803 2942 
    4 3070 3282 
    5 3295 4422 

    KEY_gm Start_gm End_gm 
    1 115000 17 
    2 284 1624 
    3 1803 2942 
    4 3070 3282 
    5 3295 4422 

Я сохранили эти два файла в «хэш». Столбец «Ключ» - это ключ, а начало и конец - значения для этих двух разных ключей.

Я написал код для сравнения этих двух хэшей и распечатал «похожие» и «не похожие» ключи из файлов.

Кодекс

my %hash_gl =(); 
my %hash_gm =(); 
open(my $fgl, "/home/gaurav/GMR/new_gl.txt") or die "Can't open the file"; 

while (my $line_gl = <$fgl>) { 
    chomp $line_gl; 
    my ($key_gl, $start_gl, $end_gl) = split("\t", $line_gl); 
    $hash_gl{$key_gl} = [ $start_gl, $end_gl ]; 
} 

while (my ($key_gl, $val_gl) = each %hash_gl) { 

    #print "$key_gl => @{$val_gl}\n"; 
} 

open(my $fgm, "/home/gaurav/GMR/new_gm.txt") or die "Can't open the file"; 

while (my $line_gm = <$fgm>) { 
    chomp $line_gm; 
    my ($key_gm, $start_gm, $end_gm) = split("\t", $line_gm); 
    $hash_gm{$key_gm} = [ $start_gm, $end_gm ]; 
} 

while (my ($key_gm, $val_gm) = each %hash_gm) { 

    #print "$key_gm => @{$val_gm}\n"; 
} 

for (sort keys %hash_gl) { 
    unless (exists $hash_gm{$_}) { 

    print "$_: not found in second hash\n"; 

    next; 
    } 

    if ($hash_gm{$_} == $hash_gl{$_}) { 
    print "$_: values are equal\n"; 
    } else { 
    print "$_: values are not equal\n"; 
    } 
} 

Пожалуйста, скажите ошибки в этом, как я не получаю желаемого output.Also, мне жаль, что я новичок в этом форуме, так что я не в состоянии сделать редактирование правильно.

+0

добавить 'использование strict' и' использование warnings' в сценарий , запустите его и посмотрите, какие ошибки вы получите ... – fugu

+0

@FlyingFrog Sir .. У меня нет ошибок после использования строгого использования и использования предупреждений также. Да, почему я запутался. –

+0

Что ** ** ** ваш желаемый результат? – simbabque

ответ

0

Предполагая, что вы хотите сравнить значения, скажем, стартовую позицию, вот как я бы это сделать:

use warnings; 
use strict; 

open my $in, '<', '1.txt' or die "$!\n"; 
open my $in2, '<', '2.txt' or die "$!\n"; 

my (%hash1, %hash2); 

while (<$in>){ 
    chomp; 
    next unless /^\s+/; 
    my ($key, $start, $stop) = /\s+(\d+)\s+(\d+)\s+(\d+)/; 
    $hash1{$key} = [$start, $stop]; 
} 

while (<$in2>){ 
    chomp; 
    next unless /^\s+/; 
    my ($key, $start, $stop) = /\s+(\d+)\s+(\d+)\s+(\d+)/; 
    $hash2{$key} = [$start, $stop]; 
} 

for my $key (sort keys %hash1){ 
    if (@{$hash1{$key}}[0] == @{$hash2{$key}}[0]){ 
     print "start matches: file1 @{$hash1{$key}}[0]\tfile2 @{$hash2{$key}}[0]\n"; 
    } 
    else {print "start doesn't match: file1 @{$hash1{$key}}[0]\t file2 @{$hash2{$key}}[0]\n"}; 
} 
+0

OP не сравнивает ключи вообще. Они сравнивают значения (которые являются массивами refs) численно и проверяют, существует ли каждый ключ первого хэша во втором хэше. – simbabque

1

После прочтения ваших файлов эти два хэша выглядят следующим образом. Я создал результат с использованием функции Data::Dump' s dd.

my %hash_gl = (
    1  => [ 114029,  17 ], 
    2  => [ 284,  1624 ], 
    3  => [ 1803,  2942 ], 
    4  => [ 3070,  3282 ], 
    5  => [ 3295,  442 ], 
    KEY_gl => [ "Start_gl", "End_gl" ], 
); 
my %hash_gm = (
    1  => [ 115000,  17 ], 
    2  => [ 284,  1624 ], 
    3  => [ 1803,  2942 ], 
    4  => [ 3070,  3282 ], 
    5  => [ 3295,  4422 ], 
    KEY_gm => [ "Start_gm", "End_gm" ], 
); 

Как вы можете видеть, значения представляют собой массивы ref. Вы помещаете их в массив refs, когда говорите $hash_gl{$key_gl} == [ $start_gl, $end_gl ]; (и то же самое для gm).

Когда вы сравниваете эти два, вы используете ==, который is used for numerical comparison. Если вы печатаете одну из $hash_gm{$_} значений, вы получите что-то вроде этого:

ARRAY(0x3bb114) 

Это потому, что это исй массива. Вы не можете сравнить их с помощью ==.

Теперь у вас есть две возможности:

  • вы можете сделать сравнение самостоятельно; чтобы сделать это, вам нужно пойти в исх массива и сравнить каждое значение:

    if ($hash_gm{$_}->[0] == $hash_gl{$_}->[0] 
        && $hash_gm{$_}->[1] == $hash_gl{$_}->[1]) 
    { 
        print "$_: values are equal\n"; 
    } else { 
        print "$_: values are not equal\n"; 
    } 
    
  • вы можете установить и использовать Array::Utils

    use Array::Utils 'array_diff'; 
    # later... 
    if (! array_diff(@{ $hash_gm{$_} }, @{ $hash_gl{$_} })) { 
        print "$_: values are equal\n"; 
    } else { 
        print "$_: values are not equal\n"; 
    } 
    

Я бы с первым решением в том, что более читабельна, потому что вам не требуется разыменование и попытка установить модуль, чтобы сохранить половину строки кода, не стоит.

0
#!/usr/bin/perl 

use warnings; 
use strict; 
use feature 'say'; 

my %hash_gl = (
    1  => [ 114029,  17 ], 
    2  => [ 284,  1624 ], 
    3  => [ 1803,  2942 ], 
    4  => [ 3070,  3282 ], 
    5  => [ 3295,  442 ], 
); 

my %hash_gm = (
    1  => [ 115000,  17 ], 
    2  => [ 284,  1624 ], 
    3  => [ 1803,  2942 ], 
    4  => [ 3070,  3282 ], 
    5  => [ 3295,  4422 ], 
); 


sub check_hash_size { 

my $hash_gl = shift; 
my $hash_gm = shift; 

if ((keys %$hash_gl) != (keys %$hash_gm)) { 
say "the hashes are 2 different sizes"; 
} 
else 
    { 
    say "the hashes are the same size"; 
    } 
} 

sub diag_hashes { 

my $hash_gl = shift; 
my $hash_gm = shift; 

for my $gl_key (keys %$hash_gl) { 
    if ( (scalar @{$$hash_gl{$gl_key}}) != (scalar @{$$hash_gm{$gl_key}}) ) { 
      say "$gl_key entry arrays are different sizes"; 
    } 
    else 
     { 
     say "arrays are the same size for key $gl_key"; 
     }   


    if ( ((scalar @{$$hash_gl{$gl_key}}) or (scalar @{$$hash_gm{$gl_key}})) > 2) { 
      say "$gl_key entry array exceeds 2 values"; 
    } 

    if ($$hash_gl{$gl_key}[0] eq $$hash_gm{$gl_key}[0]) { 
     say "$gl_key start is the same in both hashes"; 
     } 
     else 
      { 
      say "** key $gl_key start is different"; 
      }  

    if ($$hash_gl{$gl_key}[1] eq $$hash_gm{$gl_key}[1]) { 
     print "$gl_key end is the same in both hashes","\n"; 
     } 
     else 
      { 
      say "** key $gl_key end is different";  
      } 

} 


} 


check_hash_size(\%hash_gl ,\%hash_gm); 
diag_hashes(\%hash_gl ,\%hash_gm);