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

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} …
Jump to Post

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 1.21 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.