2009-08-13 11 views
10

¿Cómo comparo dos hash en Perl sin utilizar Data :: Compare?¿Cómo comparo dos hashes en Perl sin usar Data :: Compare?

+12

Bueno, miras en Data :: Compare y ves lo que hacen. ¿Por qué no quieres usar ese módulo? –

+0

duplicado posible de [Perl - Comparación de dos resumen anidada] (https://stackoverflow.com/questions/37135504/perl-compare-two-nested-hash) –

Respuesta

20

El mejor enfoque es diferente de acuerdo a sus propósitos. El elemento de preguntas frecuentes mencionado por Sinan es un buen recurso: How do I test whether two arrays or hashes are equal?. Durante el desarrollo y la depuración (y, por supuesto, al escribir pruebas unitarias), he encontrado que Test::More es útil al comparar matrices, hashes y estructuras de datos complejas. Un ejemplo sencillo:

use strict; 
use warnings; 

my %some_data = (
    a => [1, 2, 'x'], 
    b => { foo => 'bar', biz => 'buz' }, 
    j => '867-5309', 
); 

my %other_data = (
    a => [1, 2, 'x'], 
    b => { foo => 'bar', biz => 'buz' }, 
    j => '867-5309x', 
); 

use Test::More tests => 1; 
is_deeply(\%other_data, \%some_data, 'data structures should be the same'); 

Salida:

1..1 
not ok 1 - data structures should be the same 
# Failed test 'data structures should be the same' 
# at _x.pl line 19. 
#  Structures begin differing at: 
#   $got->{j} = '867-5309x' 
#  $expected->{j} = '867-5309' 
# Looks like you failed 1 test of 1. 
+2

Parece que Test :: Deep se inspiró en is_deeply. Mi pregunta es ¿cómo puedo hacer que cmp_deeply sea parte de una prueba en lugar de una prueba en sí misma? Debido a que mi lista de pruebas solo indica 8, pero cada vez que uso cmp_deeply, cuenta como una prueba, haciendo mi número real de pruebas 11 (porque llamo cmp_deeply 3 veces) cuando solo tengo 8 funciones. No quiero aumentar el número de mis pruebas. ¿Hay una solución más viable? – biznez

+0

@yskhoo. Cada vez que llamas a una de las funciones de prueba ('ok',' cmp_deeply', etc.) cuenta como una prueba. Por lo que yo sé, no hay una manera de evitar eso. Si no quiere comprometerse de antemano con un número específico de pruebas, puede hacerlo cuando cargue el módulo de prueba: 'use Test :: More qw (no_plan);'. – FMc

+5

Ya ha preguntado esto en http://stackoverflow.com/questions/1274756/how-can-i-use-perls-testdeepcmpdeeply-without-increasing-the-test-count. No respondió por qué no puede aumentar el número de pruebas, o qué tan complicado es su estructura de datos, por lo que debe llamar a cmp_deeply tres veces. Por favor, dé un paso atrás en las preguntas que está haciendo y determine cuál es el verdadero problema. Si proporciona más información, tal vez podamos ayudarlo. – Ether

3

Ver How do I test whether two arrays or hashes are equal?

FAQ de Perl y respuestas son parte de ti distribución de Perl. Puede ver la versión de esta respuesta que viene con su perl ejecutando:

$ perldoc -q equal

en su terminal.

+0

¿Cuál es la diferencia entre cmpStr y cmpStrHard de congelación-descongelación? – biznez

10

comparar no es una frase bastante detallada cuando se habla de valores hash. Hay muchas maneras de comparar los hashes:

¿Tienen el mismo número de llaves?

if (%a == %b) { 
    print "they have the same number of keys\n"; 
} else { 
    print "they don't have the same number of keys\n"; 
} 

¿Las teclas son las mismas en ambos hashes?

if (%a != %b) { 
    print "they don't have the same number of keys\n"; 
} else { 
    my %cmp = map { $_ => 1 } keys %a; 
    for my $key (keys %b) { 
     last unless exists $cmp{$key}; 
     delete $cmp{$key}; 
    } 
    if (%cmp) { 
     print "they don't have the same keys\n"; 
    } else { 
     print "they have the same keys\n"; 
    } 
} 

¿Tienen las mismas teclas y los mismos valores en ambos hashes?

if (%a != %b) { 
    print "they don't have the same number of keys\n"; 
} else { 
    my %cmp = map { $_ => 1 } keys %a; 
    for my $key (keys %b) { 
     last unless exists $cmp{$key}; 
     last unless $a{$key} eq $b{$key}; 
     delete $cmp{$key}; 
    } 
    if (%cmp) { 
     print "they don't have the same keys or values\n"; 
    } else { 
     print "they have the same keys or values\n"; 
    } 
} 

¿Son isomorfos (I saldrán de éste hasta el lector como yo particularmente no quiero probar la aplicación desde cero)?

o alguna otra medida de la igualdad?

Y, por supuesto, este código sólo se ocupa de los hashes simples. Agregar estructuras de datos complejas lo hace aún más complejo.

2

rápida, sucio, y estoy seguro de que no eficiente:

use strict; 
use warnings; 

use Data::Dumper; 

sub compare ($$) { 
    local $Data::Dumper::Terse = 1; 
    local $Data::Dumper::Indent = 0; 
    Dumper(shift) eq Dumper(shift); 
} 

my %a = (foo => 'bar', bar => [ 0 .. 3 ]); 
my %b = (foo => 'bar', bar => [ 0 .. 3 ]); 
my %c = (foo => 'bar', bar => [ 0 .. 4 ]); 

print Dumper compare \%a, \%b; 
print Dumper compare \%a, \%c; 
+1

Este enfoque más ['Text :: Diff'] (https://metacpan.org/module/Text::Diff) imprime un informe útil. – Lumi

+2

También debe hacer 'local $ Data :: Dumper :: Sortkeys = 1;' para garantizar el mismo orden de las claves. – skaurus

+0

@skaurus: ¿Por qué? ¿No estarían en el mismo orden? – zakovyrya

-1

Para comparar:

sub HashCompare { 
    my ($a, $b) = @_; 
    my %rhash_1 = %$a; 
    my %rhash_2 = %$b; 

    my $key   = undef; 
    my $hash_2_line = undef; 
    my $hash_1_line = undef; 

    foreach $key (keys(%rhash_2)) { 
    if (exists($rhash_1{$key})) { 
    if ($rhash_1{$key} ne $rhash_2{$key}) { 
    print "key $key in $file_1 = $rhash_1{$key} & $rhash_2{$key} in $file_2\n"; 
     } 
     } 
    } 
    else { 
     print "key $key in $file_1 is not present in $file_2\n"; 

      #next; 
     } 
    } 

    foreach my $comp_key (keys %rhash_1) { 
     if (!exists($rhash_2{$comp_key})) { 
      print MYFILE "key $comp_key in $file_2 is not present in $file_1\n"; 
     } 
    } 
    return; 
} 

Creación de hash sin duplicados de las llaves:

sub CreateHash { 
    my (@key_val_file) = @_; 
    my $key_count  = 1; 
    my %hash_key_val =(); 
    my $str4   = undef; 

    local $/ = undef; 

    foreach my $each_line (@key_val_file) { 
      @key_val = split(/,/, $each_line); 
      if (exists($hash_key_val{$key_val[0]})) { 
        $key_count = $key_count + 1; 
        $str4  = $key_val[0] . " occurence-" . $key_count; 
        $hash_key_val{$str4} = $key_val[1]; 
       } 
       else { 
        $hash_key_val{$key_name} = $key_val[1]; 
       } 
      } 
     } 

     $key_count = 1; 

    close FILE; 

    return %hash_key_val; 
} 
+0

por favor proporcione una explicación de su respuesta. –

+0

de donde viene $ key_name? – nurp

Cuestiones relacionadas