Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

RFC How to retrieve a hash from a hash of hashes

by bdalzell (Sexton)
on Jan 12, 2012 at 00:25 UTC ( [id://947461]=perlmeditation: print w/replies, xml ) Need Help??

As a relatively new user of Perl's hash of hashes I still find some things hard to figure out.

I have a database I am doing in perl where it is difficult to predict all the variables that might apply to a individual kind of data field and I have recently discovered that a technique used in library book cataloging where a kind of datafield may have several sub data fields can be implemented using hash of hashes and hash of arrays, etc.

For example and individual's record might have an unpredictable number of awards earned. So the awards field can be a hash with award type for the key and award date for the value.

So then I came to a point where I wanted to extract an individual's record (which is itself a hash) from the main database hash of records and assign it to a hash for sending to a subroutine for processing . Lots of searching with google failed to give me a result on "extract hash from hash of hashes and assign it to its own hash" or variations on this theme.

So I finally found the article at perldoc on hashes and hashes of hashes and used it to figure out how to retrieve an individual record as a hash. But I would like to post the solution so other people might be able to find out how it is done directly:

Original code inspiring this:

perldsc
#!/usr/bin.perl #hashes of hashes test.pl %HoH = ( flintstones => { lead => "fred", pal => "barney", }, jetsons => { lead => "george", wife => "jane", "his boy" => "elroy", }, simpsons => { lead => "homer", wife => "marge", kid => "bart", }, ); #endhoh # print the whole thing foreach $family ( keys %HoH ) { print "$family: { "; for $role ( keys %{ $HoH{$family} } ) { print "$role=$HoH{$family}{$role} "; } print "}\n"; } #print one family (which is a hash) and assign it to a hash print " print family simpsons\n"; $family ='simpsons'; for $role ( keys %{ $HoH{$family} } ) { print "\t$role=$HoH{$family}{$role} "; $simpsons{$role}=$HoH{$family}{$role}; #this works } print "}\n"; print "lead simpsons is: $simpsons{lead}\n"; #assign the families to a hash %newsimpsons = %{ $HoH{$family} }; #this works but you must provide a +value for $family %jetsons = %{ $HoH{'jetsons'} }; #this works but you must provide a va +lue in $HOH{'value'} "which can be a string print "lead simpsons is: $newsimpsons{lead}, lead jetsons is $jetsons{ +lead}\n";

Replies are listed 'Best First'.
Re: RFC How to retrieve a hash from a hash of hashes
by AnomalousMonk (Archbishop) on Jan 12, 2012 at 16:02 UTC
    ... extract an individual's record ... and assign it to a hash [to send] to a subroutine for processing ... "extract hash from hash of hashes and assign it to its own hash" ... retrieve an individual record ...

    These invocations of 'individuality' lead to a sneaking suspicion of the notion of isolation.

    The thing to remember about Perl complex data structures is that below the top-most level, it's references all the way down. And, of course, "a reference does what a reference do".

    In other words, the copy operations bdalzell shows in the OP (or should that be the OM: Original Meditation?) are 'shallow' copies: all the references involved still go trailing back to their original referents. (An example of this shown below.) Given this is the case, I find it is usually easier and less potentially self-deceptive to simply extract and pass around the references themselves rather than trying to make 'copies' of them.

    >perl -wMstrict -le "use Data::Dumper; ;; my %HoH = ( foo => { bar => { baz => { quux => 42, }, }, }, ); print Dumper \%HoH; ;; my %my_own_bar = %{ $HoH{foo}{bar} }; $my_own_bar{baz}{quux} = 'OOPS'; print Dumper \%my_own_bar; print Dumper \%HoH; " $VAR1 = { 'foo' => { 'bar' => { 'baz' => { 'quux' => 42 } } } }; $VAR1 = { 'baz' => { 'quux' => 'OOPS' } }; $VAR1 = { 'foo' => { 'bar' => { 'baz' => { 'quux' => 'OOPS' } } } };

    You have been warned.

      Indeed.

      If this were twenty-five years ago, when:

      • “Google” was a very big number and nothing more, and ...
      • People actually went to libraries, and ...
      • Libraries had card-catalogs ...
      then I would suggest the analogy that “the book itself” is over there on the shelf, while “the index card or cards that refer to that book” are right here in the various drawers.   Many cards may refer to the same book, and you can make more such cards any time you like (with the librarian’s permission, of course...), but there will still be only one book.

      You can build arbitrary data structures in Perl ... but what you are actually doing is moving-around those index cards, not the books themselves.   Perl will take you directly to the book when you use an index-card that refers to it.   Just remember that several cards can refer to the same book, and clearly keep in mind the difference between “the book” and “the card.”

      You might think of it as a Hogwarts index-card, though, because if you scribble on the index-card, a mark magically shows up on the book, and therefore every other index-card simultaneously shows the mark.   Be careful when fooling around with magic.

Re: RFC How to retrieve a hash from a hash of hashes
by sundialsvc4 (Abbot) on Jan 12, 2012 at 15:49 UTC

    Thanks for the example.

    Understanding of how to build “complex” data structures in Perl centers completely around the notion of references.   Pretty much every “value” that you can assign to anything anywhere actually consists of a dynamically allocated block of storage that has a “reference count” and that can be “garbage collected.”   You can create multiple “references to” that value, and each of those references will ultimately arrive at the same block of memory, which won” be garbage-collected (or “reaped”) until its reference-count again becomes zero.   Since the reference, itself, is a scalar value (as opposed to whatever the reference refers to...) it can become part of any data structure:   a list, an array, or a hash.   Or, more than one of these at a time.

    References are one of those brilliantly simple, simple, little, brilliant things that takes a bit of time to wrap your head around, but then “the little light comes on” and you say, purrrr....   Really, one of the very nicest things about Perl is that it makes memory so drop-dead easy to manage.   It has a very sophisticated memory manager, and, It Just Works.™

Re: RFC How to retrieve a hash from a hash of hashes
by InfiniteSilence (Curate) on Jan 13, 2012 at 18:50 UTC

    'I still find some things hard to figure out...'. Welcome to the club. There is always going to be something difficult. However, the best way I have found to reduce the frustration factor is to look for a tutorial or the right book. For dealing with hashes and getting a 'big picture' of how they work I recommend Effective Perl Programming. It has pretty pictures that show you how data types in Perl are represented as well as example code of operations you will find very useful.

    Celebrate Intellectual Diversity

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://947461]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-03-28 08:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found