2011-06-03 17 views
6

Estoy atrapado con lo que parece ser un problema conceptual simple para mí. Después de buscar diligentemente problemas similares en la Web y Stack Overflow no pude encontrar algo similar, así que pensé que podría preguntarle.¿Cómo recorro recursivamente una estructura de datos hash anidada?

Estoy construyendo un hash de hash estructura de datos que está profundamente anidada. La profundidad puede ser de 10 a 20 veces. Por el bien de este problema, estoy listando solo hasta la profundidad uno.

No puedo caminar recursivamente a través del hash de muestra a continuación en Perl. También he incluido mi código.

Me da el siguiente error:

Can't use string ("1") as a HASH ref while "strict refs" in use at

Sólo para que quede claro: mi hash es obligado a tener algunas teclas con valor 1. No puedo evitarlos.

$VAR1 = { 
    'Eukaryota' => { 
     'Rhodophyta'   => {'count' => 5}, 
     'Alveolata'   => {'count' => 16}, 
     'stramenopiles'  => {'count' => 57}, 
     'count'    => 155, 
     'Glaucocystophyceae' => {'count' => 1}, 
     'Cryptophyta'  => {'count' => 18}, 
     'Malawimonadidae' => {'count' => 1}, 
     'Viridiplantae'  => {'count' => 57}, 
    }, 
    'Bacteria' => { 
     'Cyanobacteria'  => {'count' => 1}, 
     'Actinobacteria'  => {'count' => 4}, 
     'count'    => 33, 
     'Proteobacteria'  => {'count' => 25}, 
     'Deinococcus-Thermus' => {'count' => 2}, 
     'Firmicutes'   => {'count' => 1}, 
    }, 
}; 

Código para caminar de forma recursiva este hash:

sub analyse_contig_tree_recursively { 
    my $TAXA_TREE = shift @_; 
    my $contig_hash = shift @_; 
    foreach (keys %{$TAXA_TREE}) { 
     print "$_ \n"; 
     analyse_contig_tree_recursively($TAXA_LEVEL->{$_}, $contig_hash); 
    } 
} 

Respuesta

11

No estoy seguro de lo que estás llamando analyse_contig_tree_recursively en (no se está usando el parámetro que $contig_hash en cualquier lugar, y no se han definido $TAXA_LEVEL: ¿quiso decir $TAXA_TREE?), Pero obviamente hay una falta de coincidencia entre el diseño de la estructura de datos y el patrón de recorrido recursivo. Su función transversal supone que todas las entradas son hashes, y trata los hash vacíos como el caso de terminación: si keys %{$TAXA_TREE} está vacío, no hay una llamada recursiva. Teniendo en cuenta sus datos, debe probar si un valor es un hash o no, y no recurse si encuentra que no es un hash.

sub analyse_contig_tree_recursively { 
    my $TAXA_TREE   = shift @_; 
    foreach (keys %{$TAXA_TREE}){ 
     print "$_ \n"; 
     if (ref $TAXA_TREE->{$_} eq 'HASH') { 
      analyse_contig_tree_recursively($TAXA_TREE->{$_}); 
     } 
    } 
} 
+4

o 'Scalar :: Util :: refType ($ TAXA_TREE -> {$ _}) eq 'HASH'', si la estructura de datos puede contener objetos bendecidos. – mob

+0

@Giles: Muchas gracias. No me impresiona que haya claves en mi hash que no apuntan a la referencia de hash y podrían indicar el final de la recursión. Acerca de $ TAXA_LEVEL, $ contig_hash: esas son solo algunas de las otras variables que uso para procesar. El principal problema está claro ahora y mi programa funciona ... Ustedes son rápidos e increíbles. Gracias un montón – Abhi

+0

Hombre, ustedes son rápidos. En caso de que simplemente desee ver su estructura y no necesariamente hacer nada con ella, use [Data :: Dumper] (http://perldoc.perl.org/Data/Dumper.html). Por cierto, cuando entra en hashes de hashes o listas de hashes, o listas de hash de listas, etc., es hora de empezar a pensar en la programación orientada a objetos. Toma unos minutos más configurarlo, pero puede ahorrarte mucho dolor de depuración más adelante. Lo recomiendo incluso para ofertas de una oportunidad. –

Cuestiones relacionadas