in reply to Recursive search in nested hash for selective keys

As far as I can tell from your description the following does what you want:

use warnings; use strict; my %hash = ( '-P' => 'hostPassword', 'alternate_param_options' => [ 'all', 'objects', {'-H' => ['hosting-storage-system', 'vfiler'], '-S' => ['saf'] +}, undef ], 'single_switches' => ['-N'], 'mandatory' => ['end'], '-U' => 'hostLogin' ); delve (\%hash); sub delve { my ($ref, $key) = @_; if ('ARRAY' eq ref $ref) { for my $element (@$ref) { if ($key) { delve ($element, $key); } elsif (ref $element) { delve ($element) } } return; } if ('HASH' eq ref ($ref)) { for my $nestedKey (keys %$ref) { my $value = $ref->{$nestedKey}; if ($nestedKey =~ /^-/) { delve ($value, $nestedKey) } else { delve ($value, $key) } } return; } return if ref $ref; # Some other reference type - ignore it if ($key) { printf "%22s: %s\n", $ref, $key; } }

Prints:

hostPassword: -P hosting-storage-system: -H vfiler: -H saf: -S hostLogin: -U

True laziness is hard work

Replies are listed 'Best First'.
Re^2: Recursive search in nested hash for selective keys
by perlpal (Scribe) on Aug 11, 2009 at 05:55 UTC
    Thank you , this is precisely what i'm looking for. Just wondering where my code went wrong .
Re^2: Recursive search in nested hash for selective keys
by perlpal (Scribe) on Aug 12, 2009 at 06:41 UTC
    I have slightly modified the script to return a hash reference which has keys as the "search parameter value" and values as "the corresponding key of the search parameter".

    If i pass a single hash ref to delve() , the expected output is returned. However, if i pass successive hash refs to delve() , the returned hash ref is a cumulative hash which has key-value pairs from previous function calls too.

    I need the delve function to return the the hash corresponding to input hash and not a cumulative one.

    I tried declaring the return hash with "my" but it does not work as the function is recursive.

    The modified code for delve is mentioned below :

    sub delve { my ($ref, $key) = @_; #my $key_val; if ('ARRAY' eq ref $ref) { for my $element (@$ref) { if ($key) { delve ($element, $key); } elsif (ref $element) { delve ($element) } } return ; } if ('HASH' eq ref ($ref)) { for my $nestedKey (keys %$ref) { my $value = $ref->{$nestedKey}; if ($nestedKey =~ /^-|\w/) { delve ($value, $nestedKey) } else { delve ($value, $key) } } return $key_val; } return if ref $ref; # Some other reference type - ignore it if ($key) { printf "%22s: %s\n", $ref, $key; $key_val->{$ref} = $key; return $key_val; } }

      I'd pass $key_val in as a third parameter (actually the second parameter with $key the last). However, that doesn't seem to be the real problem. I suspect all you need to do is assign an empty hash to $key_val between iterations to clear the previous contents.


      True laziness is hard work
        I passed a third parameter as $call with a value "main" if called from outside or value "sub" if called recursively within.
        $key_val = {} if ($call eq "main");