Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Tied multidimensional hashes

by davis (Vicar)
on Oct 13, 2006 at 08:52 UTC ( #578086=perlquestion: print w/replies, xml ) Need Help??
davis has asked for the wisdom of the Perl Monks concerning the following question:

I seem to be having a problem STOREing multidimensional values in a TIEd hash. I'm now going round in circles because even my minimal test case (which is typically all I need to produce to fix my own problem) isn't doing what I expect.

I've reviewed How to tie multilevel (multidimensional) hash? and the Tie::Hash documentation, and I've frankly run out of brain power.
I'm ultimately trying to concatenate keys of the subhashes together where the top-level key matches ignoring case. However, the code below doesn't even warn twice (it warns once with an empty hashref), suggesting it's broken in a stupid way I can't spot, or I'm not grokking Ties.

use warnings; use strict; use Data::Dumper; use Tie::Hash; package FlatHash; use Data::Dumper; our @ISA = qw(Tie::ExtraHash); sub STORE { my $me = $_[0]; my $key = $_[1]; my $value = $_[2]; $key = lc $key; $_[0][0]{$key} = $value; if(ref $value eq "HASH") { warn Dumper($value); } else { print "This isn't a hash\n"; } } package main; tie my %flat, "FlatHash"; $flat{Monkey}{habits} = "Eating"; $flat{monkey}{habits} = "Scratching"; warn Dumper(\%flat);
Ultimately I'd like the final datastructure to be something like:
$VAR1 = { 'monkey' => { 'habits' => ['Eating', 'Scratching'] } };
Any hints gratefully received.

davis
Kids, you tried your hardest, and you failed miserably. The lesson is: Never try.

Replies are listed 'Best First'.
Re: Tied multidimensional hashes
by shmem (Canon) on Oct 13, 2006 at 11:33 UTC
    A bit debugging like so
    sub STORE { warn "STORE: ".join(', ',map{"'$_'"} @_)."\n"; ...

    reveals

    STORE: 'FlatHash=ARRAY(0x820fd58)', 'Monkey', 'HASH(0x820fd88)'

    at the first store attempt - your $_[2] isn't what you expect. What is happening here?

    Storing the value "Eating", a FETCH is done first, which you don't see, because Tie::Hash does this for you. Since FETCH doesn't return anything, an anonymous hash is autovivified and passed into STORE as the value. This value is stored under the (lowercased) key 'monkey'. Done with the tied hash. The autovivified anonymous hash is not tied. This hash is thereafter populated with the key/value pair (habits,Eating).

    At the second assignment, the value stored under the key 'monkey' is retrieved - the anonymous hash, which is not tied, and then a normal store operation is done: the value 'Eating' in that anonymous hash is overwritten with 'Scratching'. The tied hash is involved only at FETCH.

    Did you read notice the 'FETCH' sub in Re: How to tie multilevel (multidimensional) hash?? It takes care that the value retrieved is of the right type (a tied hash), so that autovivification does not happen.

    Ultimately I'd like the final datastructure to be something like:
    $VAR1 = { 'monkey' => { 'habits' => ['Eating', 'Scratching'] } };

    This is not what you said at the beginning:

    I'm ultimately trying to concatenate keys of the subhashes together where the top-level key matches ignoring case.

    That would be

    $VAR1 = { 'monkeyhabits' => 'Scratching' }

    What are you really trying to do? And why?

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Tied multidimensional hashes
by xdg (Monsignor) on Oct 13, 2006 at 12:42 UTC

    Unless your goal is to practice reimplementing multi-dimensional tied hashes, I'd try one of the existing modules on CPAN instead. The "classic" is MLDBM. But dragonchild has done some tremendous work on DBM::Deep and I'd suggest trying that one first.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      xdg,
      I am afraid I have no idea how either of the modules you suggested would come close to accomplishing what davis is wanting to do.
      tie my %flat, "FlatHash"; $flat{Monkey}{habits} = "Eating"; $flat{monkey}{habits} = "Scratching"; warn Dumper(\%flat); __END__ Ultimately I'd like the final datastructure to be something like: $VAR1 = { 'monkey' => { 'habits' => ['Eating', 'Scratching'] } };

      To me it sounds like a variation on Data::MultiValuedHash or less likely Hash::MultiKey except that the top level is also case insensitive.

      Cheers - L~R

        I am afraid I have no idea how either of the modules you suggested would come close to accomplishing what davis is wanting to do.

        Perhaps something in DBM::Deep using filter_(fetch|store)_(key|value) would work. Severly untested, and I see the smoke from dragons rising through the fog, but I think it would be possible.

        --MidLifeXis

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://578086]
Approved by Corion
Front-paged by McDarren
help
Chatterbox?
[Corion]: choroba: Hmm - no, I keep the snippets inline, but as my framework also has support for capturing output etc., maybe I should do the same...
[Corion]: haukex: Yes, that approach is sane, and it heals the fragility of Pod parsers in a nice way while still syntax-checking stuff
[choroba]: Unfortunately, none of it is online
[haukex]: I figured that POD tests make sense, but only as author tests
[choroba]: I mean, the slides are, but not the makefile with scripts to create them
[Corion]: haukex: I've only now arrived at that revelation ;)
[Corion]: choroba: I use spod5, which also has that support, and also implements its own kinda-make stuff
[haukex]: But that module I just linked to assumes that most verbatim blocks are runnable code, I have other modules where that's not the case, so there I just copy-and-paste the synopsis into the author tests...
[haukex]: not the most efficient, but then again, I don't have that many modules on CPAN :-)
[Corion]: haukex: Yes, but if it's only supposed to run on my machine, I can be far more liberal with how I extract the code etc.

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (11)
As of 2017-02-27 12:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?






    Results (385 votes). Check out past polls.