I have a nested data structure (hash at the top level, then mixture of hashes and arrays at lower levels, arbitrarily deep)

I need to recursively search this data structure for a hash key given the value iff the hash key is a switch.

I have written a sub - routine that accomplishes this to quite some extent but fails in returning keys when the nesting level becomes deeper.

For instance , running the code on the nested hash below results in

$VAR1 = { '-P' => 'hostPassword', 'alternate_param_options' => [ 'all', 'objects', { '-H' => [ 'hosting-storage- +system', 'vfiler' ], '-S' => [ 'saf' ] }, undef ], 'single_switches' => [ '-N' ], 'mandatory' => [ 'end' ], '-U' => 'hostLogin' };

Output : (switches are not taken as parameters in the logic implemented)

Param List : hostPassword all objects hosting-storage-system vfiler sa +f end hostLogin Value : hostPassword Key : -P Value : all Key : Value : objects Key : Value : hosting-storage-system Key : Value : vfiler Key : Value : saf Key : Value : Key : Value : end Key : Value : hostLogin Key : -U

I get correct keys for "hostpassword" as "-P" and "hostLogin" as "-U" . The value "all" has no key as "alternate_param_options" is not a switch .

The issue lies with the values "hosting-storage-system" and "vfiler" which should have "-H" as assigned keys ; and "saf" which should have "-S" as assigned key.

The code is mentioned in the link below :

my $test_hash1 = { '-P' => 'hostPassword', 'single_switches' => [ '-N' ], 'alternate_param_options' => [ 'all', 'objects', { '-H' => [ 'hosting-storage- +system', 'vfiler' ], '-S' => [ 'saf' ] }, $VAR1->{'alternate_param_opti +ons'}[2] ], 'mandatory' => [ 'end' ], '-U' => 'hostLogin' }; print Dumper($test_hash1); my @param_list = get_param_list ($test_hash1); print "\nParam List : @param_list\n"; foreach my $element (@param_list){ print "\nValue : $element\n"; my $key = getKeyValue($test_hash1,$element,"HASH"); print "\nKey : $key\n"; } sub get_param_list{ my $_cli_ref = shift; my @_param_list; my ($_key,$_value,$_element); #print ref $_cli_ref,"\n"; if ((ref $_cli_ref) =~ /.*?HASH.*/i){ while (($_key,$_value) = each %$_cli_ref){ #print "\nKey : $_key\nValue : $_value\n";getc +(); if ($_value =~ /.*?ARRAY.*/i){ push (@_param_list,get_param_list($_va +lue)); }elsif($_value =~ /.*?HASH.*/i){ push (@_param_list,get_param_list($_va +lue)); }else{ push (@_param_list,$_value) if ($_valu +e !~ /^\-[a-zA-Z]{1}/); } } } if ((ref $_cli_ref) =~ /.*?ARRAY.*/i){ foreach $_element (@$_cli_ref){ #print "\nElement : $_element\n"; if ($_element =~ /.*?ARRAY.*/i){ push (@_param_list,get_param_list($_el +ement)); }elsif($_element =~ /.*?HASH.*/i){ push (@_param_list,get_param_list($_el +ement)); }else{ push (@_param_list,$_element) if ($_el +ement !~ /^\-[a-zA-Z]{1}/); } } } return @_param_list; } sub getKeyValue { my $_syn_tree = shift; my $_value = shift; my $_type = shift; my ($_hkey,$_hvalue); my $_key ; my $_key1 ; my $_found ; if ((ref $_syn_tree) =~ /.*?HASH.*/i){ while(($_hkey,$_hvalue) = each %$_syn_tree){ if ($_hvalue =~ /.*?(HASH).*/i){ $_key = getKeyValue($_hvalue,$_value,$ +1); }elsif($_hvalue =~ /.*?(ARRAY).*/i ){ $_key1 = $_hkey if($_hkey =~ /\-[a-zA- +Z]{1}/); $_found = getKeyValue($_hvalue,$_value +,$1); $_key = $_key1 if ($_found == 1); }elsif($_hvalue eq $_value){ $_key = $_hkey if($_hkey =~ /\-[a-zA-Z +]{1}/); }else{ } } } if((ref $_syn_tree) =~ /.*?ARRAY.*/i){ foreach (@$_syn_tree){ if ($_ eq $_value){ $_found = 1; }elsif($_ =~ /.*?(ARRAY).*/i){ $_found = getKeyValue($_,$_value,$1); }elsif($_ =~ /.*?(HASH).*/i){ $_key = getKeyValue($_,$_value,$1); }else{ } } } return $_key if ($_type eq "HASH"); return $_found if ($_type eq "ARRAY"); }
Seeking advice to enhance my code. Thanks in Advance!

In reply to Recursive search in nested hash for selective keys by perlpal

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.