[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