[tpm] Solved: Re: Populating an unfixed number of hash elements
Madison Kelly
linux at alteeve.com
Thu Jun 19 10:08:08 PDT 2008
I responded to this some time ago, but neglected to include TPM in the
reply-to. I hope people don't mind me re-sending this after so much
time, but I wanted to get in into the archives, in case it helps someone
down the road.
The variation I used is at the end of this message. Thanks again, Shaun
and Viktor!
Madi
Shaun Fryer wrote:
> Nice and small. I like it. Here's the alternate solution I just came up with.
> Like yours, uses a recursive helper function, but also works with a global hash.
>
> ################################################################################
> use strict;
> use warnings;
> use Data::Dumper;
>
> my $string1="some::string::of::elements";
> my $string2="some::string";
> my $string3="some::string::of::other::elements";
> my $string4="another::set::of::keys";
>
> my %hash = ();
>
> mk_href(\%hash, $string1, "a value");
> mk_href(\%hash, $string2, 12);
> mk_href(\%hash, $string3, "a really long string that takes up pages");
> mk_href(\%hash, $string4, "something else again.");
> print Dumper \%hash;
>
> sub mk_href {
> my ($href, $keystr, $value) = @_;
> my @keys = split /::/, $keystr;
> my $last_key = pop @keys;
> my $_href = {};
> $_href->{$last_key} = { $value => 1 };
> while (my $key = pop @keys) {
> my $elem = {};
> $elem->{$key} = $_href;
> $_href = $elem;
> }
> add_href($href, $_href);
> }
>
> sub add_href {
> my ($href1, $href2) = @_;
> for my $key (keys %$href2) {
> if (ref $href1->{$key} eq 'HASH') {
> add_href( $href1->{$key}, $href2->{$key} );
> } else {
> $href1->{$key} = $href2->{$key};
> }
> }
> }
> ################################################################################
> --
> Shaun Fryer
> cl: 905-920-9209
>
> On Fri, May 09, 2008 at 02:00:39PM -0400, Viktor Pavlenko wrote:
>>>>>>> "SF" == Shaun Fryer <sfryer at sourcery.ca> writes:
>> SF> Actually, this may be more what you intended. However, notice
>> SF> that the key/value may get over-ridden in case of
>> SF> collisions.
>>
>> If she avoids global hash, there will be no problem ...
>>
>> SF> sub mk_href {
>> SF> my ($href, $keystr, $value) = @_;
>> SF> my @keys = split /::/, $keystr;
>> SF> my $last_key = pop @keys;
>> SF> my $_href = {};
>> SF> $_href->{$last_key} = $value;
>> SF> while (my $key = pop @keys) {
>> SF> my $elem = {};
>> SF> $elem->{$key} = $_href;
>> SF> $_href = $elem;
>> SF> }
>> SF> $href->{$_} = $_href->{$_} for keys %$_href;
>> SF> }
>>
>> ... and then this:
>>
>> -------------------------------------------------------------------->8
>> sub mk_href
>> {
>> my ($keystr, $value) = @_;
>> my @keys = reverse split /::/, $keystr;
>> helper($value, @keys);
>> }
>>
>> sub helper
>> {
>> my ($val, @keys) = @_;
>> my $k = pop @keys;
>> my $hr = {};
>> $hr->{$k} = ($#keys == -1) ? $val : helper($val, @keys);
>> return $hr;
>> }
>> -------------------------------------------------------------------->8
>>
>> --
>> Viktor
>>
> _______________________________________________
> toronto-pm mailing list
> toronto-pm at pm.org
> http://mail.pm.org/mailman/listinfo/toronto-pm
>
Thank you both very kindly!
I needed to make a slight change, but the final example was close to
perfect. The only real difference was that you're example was using the
$value as a final key in the hash, set to a value of '1'. I needed the
'$value' to be the contents of the hash string.
For reference:
-=-=-=-=-=-
# Contributed by Shaun Fryer and Viktor Pavlenko by way of GTALUG.
sub _mk_href
{
my $self=shift;
my $href=shift;
my $key_string=shift;
my $value=shift;
if ($self->{CHOMP_ROOT}) { $key_string=~s/\w+:://; }
my @keys = split /::/, $key_string;
my $last_key = pop @keys;
my $_href = {};
$_href->{$last_key}=$value;
while (my $key = pop @keys)
{
my $elem = {};
$elem->{$key} = $_href;
$_href = $elem;
}
$self->_add_href($href, $_href);
}
sub _add_href
{
my $self=shift;
my $href1=shift;
my $href2=shift;
for my $key (keys %$href2)
{
if (ref $href1->{$key} eq 'HASH')
{
$self->_add_href( $href1->{$key}, $href2->{$key} );
}
else
{
$href1->{$key} = $href2->{$key};
}
}
}
-=-=-=-=-=-
The '$self=shift;' line is needed as these are methods in a module, so
'$self' is the first value shifted in. The leading '_' is just to
indicate that, in my case, these are internal methods.
The '$_href->{$last_key}=$value;' is what I changed to have the value be
the stored data. Lastly, 'if ($self->{CHOMP_ROOT}) {
$key_string=~s/\w+:://; }' is an internal variable that I use the check
I am to mimic XML::Simple's habit of dropping the initial hash reference
(no, I have no idea why it does this, but I need my module to be a
drop-in replacement for it, so...).
Thanks again, you guys were a huge help!
Madi
More information about the toronto-pm
mailing list