[Phoenix-pm] Multi-level hash - quick key reference?

Metz, Bobby W, WWCS bwmetz at att.com
Thu Jun 8 21:27:38 PDT 2006


well, couldn't get the 

$hash{(qw/foo bar baz quux/)} = 20;

to work when trying to use say qq/$index/ for variable interp.  So I
finally did the evil approach as Brock put it.  Should have just done
this first without futzing with all the other weird and wacky ways I
tried that I'm too ashamed to post.

So, short of flattening the hash which I'll likely due for memory
reasons, here's the eval I came up with.  Note: Users may enter values
like .1.2.3.4 or 1.2.3.4 for searching, just in case you disagree with
my sub.

$val{1}{2}{3}{4} = "Hello World";
$index = ".1.2.3.4";

$index =~ s/^\.+//;						#
Watching for typos
$index =~ s/\.+$//;						# Ditto
$index =~ s/\.+/}{/g;
$value = '$val{' . $index . '}';
print $value . " = " . eval("$value") . "\n";

But, as it turned out my concern over hash memory was valid.  A test
file with 46324 records resulted in the following crude measurements:

Single hash index & value
	Avg time to load hash = 3s
	Memory usage = 23M

Multi-dimension hash index & value
	Avg time to load hash = 15s
	Memory usage = 103M

Even using the "keys %hash = xxxxx" to pre-malloc didn't seem to save
any time, but did increase the memory usage since Perl rounds up to a
power of 2.

Guess I'll be sticking with the flat index.  I was going to test random
hash value lookup times but the poor load/mem performance of the
multi-index approach doesn't make it worthwhile.

Brock/Scott,
	Thanks to all for the input.

Bobby

-----Original Message-----
From: Scott Walters [mailto:scott at illogics.org]
Sent: Wednesday, June 07, 2006 4:11 PM
To: Metz, Bobby W, WWCS
Cc: phoenix-pm at pm.org
Subject: Re: [Phoenix-pm] Multi-level hash - quick key reference?


Hey Bobby,

I can try to track this down if you like, but xmath has a patch to Perl
that modifies
the grammar to recogize ` as something like . in JavaScript, so you can
write 
$hash`foo`bar`baz to mean $hash{foo}{bar}{baz}.  Matching braces are
tedious to type.

Data::Alias is nice for making little shortcuts, too:

use Data::Alias;
alias my $bucket = $hash{foo}{bar}{baz}{quux};
$bucket = 20;
print $hash{foo}{bar}{baz}{quux}, "\n"; # 20

If you are designing the datastructure from the beginning, there's the
old Perl 4
multidim syntax:

$hash{'foo', 'bar', 'baz', 'quux'} = 20;
$hash{(qw/foo bar baz quux/)} = 20;

That's not the same thing as writing $hash{foo}{bar}{baz}{quux} but if
the
keys don't contain binary data and you don't need to list the keys at a
given depth, it's about as useful.

You could also write an lvalue 'dehash' method using Data::Alias:

use Data::Alias;

sub dehash (\%;@) :lvalue {
    my $ref = $_[0];
    for my $i (1..$#_) {
        $ref ||= { }; #manualvivicate
        alias $ref = $ref->{$i};
    }
    $ref;
}

my %hash;
dehash(%hash, qw/foo bar baz/) = 10;
print dehash(%hash, qw/foo bar baz/), "\n";

lvalue assignments to a scalar that's aliased and Perl doesn't dump
core.  W00t!

-scott

On  0, "Metz, Bobby W, WWCS" <bwmetz at att.com> wrote:
> All,
> 	I'm looking for a quicker method of accessing elements in a
multi-level hash.  For example, the hash will have values like so
> 
> $hash{1}{2}{3} = "Hello World";
> $hash{1}{3}{4}{5} = "the quick brown fox";
> 
> The input to the program comes from another I can't control which will
ouput values like so:
> 
> .1.2.3<tab>Hello World
> .1.3.4.5<tab>the quick brown fox
> 
> Parsing the values is cake, but what I'm looking for is a faster way
to get values in/out of the hash using the ".1.2.3".  Is there some
method that allows for arbitrary hash levels without coding using for
loops?  I mean clearly recursion would solve this but I was hoping there
was something more simple.  Or is recursion the only answer.  I was
hoping for something like this, but I know this example doesn't work.
I've searched for a bit but I must be asking the right questions of
mighty google.
> 
> $index = ".1.2.3";
> $index =~ s/^\.//g;
> $index =~ s/\./}{/g;
> print $hash{$index} . "\n";
> 
> Thoughts?
> 
> Thanks,
> 
> Bobby
> _______________________________________________
> Phoenix-pm mailing list
> Phoenix-pm at pm.org
> http://mail.pm.org/mailman/listinfo/phoenix-pm


More information about the Phoenix-pm mailing list