Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.

Hash Nightmare

by Limo (Scribe)
on Oct 06, 2000 at 20:53 UTC ( #35606=perlquestion: print w/replies, xml ) Need Help??

Limo has asked for the wisdom of the Perl Monks concerning the following question:

Well, if this question doesn't get me banned, then I've found a home. I am STILL having the same problem, although, I can probably ask a more specific question. So, here goes:
%hash1 %hash2 %hash3 %hash4
all have identical keys, different values. Each hash is populated in a different subroutine. I would like (need!) to print the contents as shown:
key 1 value key 1, hash 1 value key 1, hash 2 value key 1, hash 3 value key 1, hash 4 key 2 value key 2, hash 1 value key 2, hash 2 value key 2, hash 3 value key 2, hash 4 etc.........
I know that I have referred to this problem in previous posts, but I ask again, because I am pretty desperate at this point, AND I think that I am presenting the question in a more concise manner. Could some kind monk lend a hand?

Replies are listed 'Best First'.
Re: Hash Nightmare
by swiftone (Curate) on Oct 06, 2000 at 21:10 UTC
    I'll expound on merlyn's comments.

    To use your data structures, you can do this:

    #create list of hashes my @allhashes = ( \%hash1, \%hash2, \%hash3 ); #note the following assumes all keys exist and are the same #keys are not sorted in this example foreach my $key (keys %hash1) { print "key $key\n"; foreach my $hash (@allhashes) { print "Value: $hash->{$key}\n"; } }
    The better way to do it, as merlyn said, is to create your nested data structure from the top. Rather than creating (N) different hashes with the same keys, create a list of hash references (just like @allhashes above), and populate that with whatever method you are populating your hashes with now.

    Re-Update: Deleted a bunch of stuff that I thought was relevant, but wasn't.

(tye)Re: Hash Nightmare
by tye (Sage) on Oct 06, 2000 at 21:53 UTC

    You can convert your data via something like:

    my $devs= hashjoin( { version=>\%vers, module=>\%mod, memory=>\%mem } ); sub hashjoin { my( $in )= @_; my $out= {}; for my $attrib ( keys %$in ) { for my $item ( keys %{ $in->{$attrib} } ) { $out->{$item}->{$attrib}= $in->{$attrib}->{$item}; } } return $out; }
    I could factor that a little differently but I chose this way because I'm not assuming that all of your hashes actually do have the exact same keys and I didn't feel like checking that assumption.

    Here is yet another case where I really want my "dereference an entire list at a time" operators. Then I could replace that middle loop with:

    $out->@{ keys $in->{$attrib}->% }-->{$attrib}= values $in->{$attrib}->%;
    and it would make it easier for you to build your hashes this way from the beginning. (And, no, that last bit of code isn't valid Perl -- it is what I wish Perl supported: -->, ->%, ->@, ->@{}, ->@[], ->$, etc.)

    I'd love to see an elegant method for generating the data in the format that merlyn suggested from the beginning, if each attribute is gathered from a different subroutine.

            - tye (but my friends call me "Tye")
Re: Hash Nightmare
by elusion (Curate) on Oct 06, 2000 at 21:07 UTC
    @keys = ("key1","key2,"key3","key4"); foreach $key (@keys) { print "$key\n"; print "$hash1{$key} , \$hash1\n"; print "$hash2{$key} , \$hash2\n"; print "$hash3{$key} , \$hash3\n"; print "$hash4{$key} , \$hash4\n\n"; }
    I think this should work. But no guarentees.

    - p u n k k i d
    "Reality is merely an illusion, albeit a very persistent one." -Albert Einstein

      All the keys in each hash are the same so couldn't you do the following:

      foreach (keys %hash1) { ... # here you would use $_ as the variable for the keys }
      This eliminates the creation of the @keys and $key variables. Hope that helps.

      Zenon Zabinski | zdog |

RE: Hash Nightmare
by Limo (Scribe) on Oct 06, 2000 at 21:22 UTC
    the data looks like:
    %hash 1 keys = device names values = software version %hash 2 keys = device names values = "module 1\n module 2 \n......." %hash 3 keys = device names values = either "$pub" or "$prv", depending upon device %hash 4 keys = device names values = amount of memory
    For each device, I want to print:
    "device name" "===========" "software version" "module 1" "module 2" "module 3....." "public": ($pub, if defined) "private": ($prv if defined) "amount of memory"
    Does this help?
      Restructure your data so you have:
      %device_info = ( device1 => { version => '1.4', module => [1, 2, 3], memory => '18k' +}, device2 => { version => '1.4', module => [4,5,6], memory => '25k' }, device3 => { version => '1.2', module => [7,8,9], memory => '18k' }, );
      Then it's easy to do operations in parallel. Having upside-down data structures is nasty.

      -- Randal L. Schwartz, Perl hacker

      The code I posted above should print this out (with some cosmetic work to the print statements, and some "if exists" statements). You really should look into making this a structure like the one merlyn posted though.

      Give it a shot, and reply with any errors you get.

        As I am relatively new to Perl, I have no idea what merlyn was talking about.
Re: Hash Nightmare
by merlyn (Sage) on Oct 06, 2000 at 21:01 UTC

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://35606]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2023-09-26 03:42 GMT
Find Nodes?
    Voting Booth?

    No recent polls found