2011-06-03 6 views
6

Utknąłem z czymś, co wydaje mi się prostym problemem koncepcyjnym. Po pilnym szukaniu podobnych problemów w Internecie i przepełnieniu stosu nie mogłem znaleźć czegoś podobnego, więc pomyślałem, że mogę cię zapytać.Jak rekurencyjnie przejść strukturę zagnieżdżonych danych hashowych?

Buduję mieszanie struktury hashowej, która jest głęboko zagnieżdżona. Głębokość może wynosić 10-20 razy. Ze względu na ten problem wymieniam tylko do pierwszej głębokości.

Nie mogę rekurencyjnie przejść przez przykładowy skrót w Perlu. Zawarłem również mój kod.

Daje mi następujący błąd:

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

Tak więc jest oczywiste: my hash jest związana mieć pewne klucze o wartości 1. Nie można ich uniknąć.

$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}, 
    }, 
}; 

Kod rekursywnie chodzić ten 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); 
    } 
} 

Odpowiedz

11

nie jestem pewien co dzwonisz analyse_contig_tree_recursively na (nie używasz że $contig_hash parametr w dowolnym miejscu, a nie zdefiniowano $TAXA_LEVEL: czy miałeś na myśli $TAXA_TREE?), Ale jest oczywiście niedopasowanie między układem struktury danych a rekurencyjnym wzorcem przejścia. Twoja funkcja traversal zakłada, że ​​wszystkie wpisy są hashami i traktuje puste hashe jako przypadek zakończenia: jeśli keys %{$TAXA_TREE} jest pusty, nie ma rekursywnego wywołania. Biorąc pod uwagę twoje dane, musisz sprawdzić, czy wartość jest hash, czy nie, i nie powtarzaj się, jeśli okaże się, że nie jest 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

lub 'Scalar :: Util :: reftype ($ TAXA_TREE -> {$ _}) eq„HASH'', jeśli struktura danych może zawierać błogosławione obiektów. – mob

+0

@Giles: Wielkie dzięki. Zauważyłem, że w haśle znajdują się klucze, które nie wskazują odniesienia do skrótu i ​​mogą sygnalizować koniec rekursji. Informacje o $ TAXA_LEVEL, $ contig_hash: to tylko niektóre z innych zmiennych, których używam do przetwarzania. Główny problem jest teraz jasny i mój program działa ... Jesteście szybcy i niesamowici. Dzięki. – Abhi

+0

Człowieku, jesteście szybcy. Jeśli chcesz po prostu zobaczyć swoją strukturę i niekoniecznie coś z nią zrobić, użyj [Data :: Dumper] (http://perldoc.perl.org/Data/Dumper.html). BTW, kiedy dostajesz hasze haszów lub listy skrótów lub listy skrótów list itd., Czas zacząć myśleć o programowaniu zorientowanym obiektowo. Poświęć kilka minut na konfigurację, ale później możesz zaoszczędzić wiele cierpienia podczas debugowania. Polecam go nawet w przypadku ofert jednorazowych. –