Hi Daniwebbers,
can someone help me How to figure out the depth of a dynamic hash (hash of hashes) in perl. If it has consistent structure, we can traverse through while/foreach and find out the depth. Could anyone point me the right and best way to figure it out.

my %hash1 = (

    name => {
            first => "John",
            last => "branham",
            middle => "visa",
        },
    address => {
            park => "cubbon",
            doorno => "4/6",
            other => {
                division => "division",
                city => "Cincinati",
                state => "Ohio",
                country => {
                    cont => "NA",
                    code => "USA",
                    pin => "51123",

                },
                district => "district",

                }

    },
    status => "unmarried"
);

%hash2 might or might not have the structure.. for instance.. address might be blank.
Inshort am in need of a subroutine which could take an hash as an argument and return (highest) depth of the hash above example is 5 . $href->{"hash1"}->{"address"}->{other}->{country}->{code}.

I tried with recursive funtion. but with no success..
Any help would be highly appreciated.. Thanks

Recommended Answers

All 3 Replies

Hi,
Please sorry, this reply is coming this later. It's better later than never... :)

I think basically, all you needed is a recursive subroutine. Using ref to check the value dataset.

Something like this:

sub dump_data {
    my $ref = shift;

    for ( keys %{$ref} ) {
        print $_, '=>';
        if ( ref $ref->{$_} eq 'HASH' ) {
            dump_data( $ref->{$_} );  ## sub called itself
        }
        else { print $ref->{$_}, $/ }
    }
}

It would print all your keys and values out. However, you can twist that a bit to get you what you wanted. Like so:

#!/usr/bin/perl
use warnings;
use strict;

my %hash1 = (

    name => {
        first  => "John",
        last   => "branham",
        middle => "visa",
    },
    address => {
        park   => "cubbon",
        doorno => "4/6",
        other  => {
            division => "division",
            city     => "Cincinati",
            state    => "Ohio",
            country  => {
                cont => "NA",
                code => "USA",
                pin  => "51123",

            },
            district => "district",

          }

    },
    status => "unmarried"
);

 my $start_level = 0;

dump_data( \%hash1, $start_level );

sub dump_data {
    my ( $ref, $level ) = @_;

    die "You can only pass an HASH reference data"
      unless ref $ref eq 'HASH';

    for ( keys %{$ref} ) {
        print $/, 'Level ', $level, "\t" x $level, $_, '=>';
        if ( ref $ref->{$_} eq 'HASH' ) {
            dump_data( $ref->{$_}, ++$level );    ## sub called itself
        }
        else { print $ref->{$_}, $/ }
    }
}

It's print out all the keys, values and the Levels of each. You are free to modify this, if it doesn't server your purpose.

absolutely stunning. This was exactly I was looking for.

I would like to make a small addition, since I believe that this is not a fully answered question. When calling the data_dump function recursively, you need to make sure you substract 1 from your $level after it's been called to make sure the cascading of many levels deep hashes works correctly. Otherwise you can end up having same category elements at different levels.

print $/, 'Level ', $level, "\t" x $level, $_, '=>';
if ( ref $ref->{$_} eq 'HASH' ) { 
    dump_data( $ref->{$_}, ++$level ); ## sub called itself 
    --$level; ######## ADD THIS 
    } 
else { print $ref->{$_}, $/ }

  if ( ref $ref->{$_} eq 'HASH' ) { 
        dump_data( $ref->{$_}, ++$level ); ## sub called itself 
        --$level; ######## ADD THIS 
    } else { 
        print $ref->{$_}, $/ 
    }
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.