Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

Set up a recursive routine to assign existing values of a hash reference to the existing keys of the hashref. Recursion happens when you find one of the values is itself a hashref, when the routine is called on itself again. You may need to check for duplicated values across the different depths though. This is untested but, you get the idea.

my $newhashref = {}; sub rechash { my $href = shift; foreach (keys %$href){ &rechash($href->{$_}) if ( ref($href->{$_}) && ref($href->{$_}) eq +'HASH'); $newhashref->{$_} = $href->{$_}; #update added '->' dereferencing. } return $newhashref; } my $ref_to_onelevelhash = rechash $ref_to_multilevelhash;

update after testing:

There is a slight expense with this solution. Where the value is a hash reference, after recursing, the reference to the hash will then be copied as a new value to the key of the same name. To extract each key and (actual)value pair the foreach if conditional needs to become a full expression, including the post recursion assignment. By which I mean...

#! \usr\bin\perl use strict; use warnings; my $mlh = my $multilevelhash = {}; $mlh->{spiral} = 'staircase'; $mlh->{polymorph}{psyche} = { dream => 'Coyote', daydream => 'Eagle'}; $mlh->{polymorph}{physic} = { solid => 'liquid', liquid => 'gas'}; #$mlh->{polymorph}{psyche}{meditation} = { daydream => 'Coyote', omnip +otent => 'all hinges'}; ## uh oh duplicate keys at different levels. +.. # my $refnewhas = {}; # see 'update' - switch comments my $refnewhash = {}; sub rechash { #my $refnewhash = $refnewhas; # see 'update' my $href = shift; foreach(keys %$href){ if (ref($href->{$_}) && ref($href->{$_}) eq 'HASH'){ &rechash($href->{$_}) }else{ $refnewhash->{$_} = $href->{$_}; } } # return $refnewhash; # see update - switch comments return; } # my $unihash = rechash $mlh; # update - switch rechash $mlh; # update - switch foreach #foreach(keys %$unihash){ # print "\n",$_," is ",$unihash->{$_}; #}; foreach(keys %$refnewhash){ print "\n",$_," is ",$refnewhash->{$_}; };

However if you just need to strip out keys that hold hash references into a single level hash, use the first if consruct. The actual values will also be flattened. Notice also, that this sub does not need to specify the return reference. But does need the return statement.

Update: I am troubled by returning a variable initially declared outside the sub. In attempting to resolve the return value, I couldn't set up the newhashref inside the sub as it is recursive and would be clobbered through each pass. If I set the value to an our lexical it will work, but not by local. The simplest solution that works and contains the reference to be passed within the routine is to 'uncomment' the code. But its starting to get a little messy now... EOU

update solved. $refnewhash is in scope within the sub, so it does not need to be passed or copied in. And no return statement is required. $refnewhash has been loaded by the subroutine. However return statments depend on the calling context. If you are assigning to $unihash you will need to return a scalar reference such as return $refnewash or return \%$refnewhash. This in turn is a little redundant (seeing as we are not modifiying $href) as it is effectively the same as copying a reference of a loaded $refnewhash to $unihash after calling rechash $mlh. EOU


In reply to Re: Hashes Question by Don Coyote
in thread Hashes Question by anshumangoyal

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, 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, 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.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others imbibing at the Monastery: (7)
    As of 2018-06-22 19:50 GMT
    Find Nodes?
      Voting Booth?
      Should cpanminus be part of the standard Perl release?

      Results (124 votes). Check out past polls.