Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Traverse an unknown multi-dimensional hash

by Anonymous Monk
on Jul 12, 2007 at 09:45 UTC ( #626183=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone,

Say you had an unknown hash structure and you didnt know how many dimensions to it there were. By dimension I mean child hashes, so it could be HoH, HoHoH, HoHoHoH, and so on, you just dont know.

How would you traverse this hash to print out all key => value pairs. The only way I know how is a series of for loops, however that would mean you have to know in advance how deep it goes.

for my $k1 ( sort keys %{ $self->{"_dataSymbols"} } ) { print "$k1\n"; for my $k2 ( sort keys %{ $self->{"_dataSymbols"}->{ $k1 }} ) { print "\t$k2\n"; for my $k3 ( sort keys %{ $self->{"_dataSymbols"}->{ $k1 }->{ + $k2 } } ) { print "\t\t$k3\n"; for my $k4 ( sort keys %{ $self->{"_dataSymbols"}->{ $k1 } +->{ $k2 }->{ $k3 } } ) { print "\t\t\t$k4\n"; for my $k5 ( sort keys %{ $self->{"_dataSymbols"}->{ $k +1 }->{ $k2 }->{ $k3 }->{ $k4 } } ) { print "\t\t\t\t$k5\n"; for my $k6 ( sort keys %{ $self->{"_dataSymbols"}->{ + $k1 }->{ $k2 }->{ $k3 }->{ $k4 }->{ $k5 } } ) { print "\t\t\t\t\t$k6 => %{ $self->{"_dataSymbols" +}->{ $k1 }->{ $k2 }->{ $k3 }->{ $k4 }->{ $k5 } }\n"; } } } } } }
Any help is greatly appreciated, thanks in advance, Mich.

Replies are listed 'Best First'.
Re: Traverse an unknown multi-dimensional hash
by GrandFather (Saint) on Jul 12, 2007 at 10:46 UTC

    Recursion is the trick:

    use strict; use warnings; my %hash = ( 1 => { a => { i => 'level 3', ii => 'level 3', iii => 'level 3', }, b => { i => 'level 3', ii => 'level 3', iii => 'level 3', }, }, 2 => {a => 'level2', b => 'level2'}, 3 => 'level 1', 4 => 'level 1', ); print dumpHash(\%hash); sub dumpHash { my ($element, $indent) = @_; $indent ||= ''; return "$indent$element\n" unless 'HASH' eq ref $element; my $str= ''; for my $key (sort keys %$element) { $str .= "$indent$key =>\n"; $str .= dumpHash ($element->{$key}, $indent . ' '); } return $str; }

    Prints:

    1 => a => i => level 3 ii => level 3 iii => level 3 b => i => level 3 ii => level 3 iii => level 3 2 => a => level2 b => level2 3 => level 1 4 => level 1

    DWIM is Perl's answer to Gödel
      how would i do something like 1 => a =>i =>level 3
      1=> a=> =>ii => level3
      1=>a=>iii=>level3
      etc.... Please help
        How would i print the output like this : 1 => a =>i =>level 3 1=> a=> =>ii => level3 1=>a=>iii=>level3 etc I could not workout the code to go back to the start and traverse back.
Re: Traverse an unknown multi-dimensional hash
by Tomte (Priest) on Jul 12, 2007 at 10:30 UTC

    How would you traverse this hash to print out all key => value pairs. The only way I know how is a series of for loops, however that would mean you have to know in advance how deep it goes.
    If printing is all you want, use Data::Dumper or one of its kind as suggested - if you want to code the stuff yourself (anybody smelling homework here?), or have really completly different needs than printing, then have a look at ref, which you can use to determin the datatype of the inspected value, and thus to decide what action to take (recurse into another hash, recurse into array, print a scalar, ...). A recursive implementation will be easiest to implement - however if the structures you expect are deeply nested, I'd use a stack to implement an iterative solution.

    regards,
    tomte


    An intellectual is someone whose mind watches itself.
    -- Albert Camus

      Thanks, your help is appreciated, i've managed to print out what I want working using Data::Dumper. I just needed to testing whether a particular hash holds the information I need. You can "smell" homework all you like but it wasnt the case. Why cant it be a newbie getting to grips with programming, who wants to change some existing code he has found? Half of learning to program is not only writing your own code but understanding and altering existing code, is it not?

        Why cant it be a newbie getting to grips with programming, who wants to change some existing code he has found?
        It certainly can - therefore I answered with the pointers to the solution GrandFather provided in code - it would have helped you in either case.
        I just needed to testing whether a particular hash holds the information I need.
        Then why didn't you state that in your posting? While printing the whole datastructure and scanning it manually is surly working, solutions to search for particular values/keys in an arbitrary structured hash aren't that hard to achieve either :-)

        Acting as anonymonk and asking seemingly simple to answer questions doesn't help getting a lot of trust in advance, at least with me.

        A newbie getting to grips with programming in Perl could certainly go to alot of places worse than perlmonks, but not that many better suited to advance your skills: Please register an account, read Welcome to the Monastery! Make yourself at home., have a look around - and be indeed welcome.

        regards,
        tomte


        An intellectual is someone whose mind watches itself.
        -- Albert Camus

Re: Traverse an unknown multi-dimensional hash
by citromatik (Curate) on Jul 12, 2007 at 09:51 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://626183]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (2)
As of 2021-12-08 01:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    R or B?



    Results (34 votes). Check out past polls.

    Notices?