On Sun, Apr 13, 2008 at 5:45 PM, Randal L. Schwartz <[EMAIL PROTECTED]> wrote: > >>>>> "Kelly" == Kelly Jones <[EMAIL PROTECTED]> writes: > > Kelly> I have a file with this in it: > Kelly> a.b = 10 > Kelly> c.d.e = 11 > Kelly> f.g.h.i.j.k = 12 > > Kelly> Based on that, I want to set: > > Kelly> $HASH{a}{b} = 10; > Kelly> $HASH{c}{d}{e} = 11; > Kelly> $HASH{f}{g}{h}{i}{j}{k} = 12; > > Kelly> This is easy using eval(), but is there a better way? > > Yes. http://www.perlmonks.org/index.pl?node_id=443584 snip
At least in Perl 5.8.8 the for loop solution is faster (significantly so for the get case), but the reduce solution is more general. When only getting values, the reduce method autovivifies keys; this could cause errors in the program later. get_for didn't autovivify 42 42 get_pte did autovivify 42 42 get_reduce did autovivify 42 42 set_for 42 42 set_pte 42 42 set_reduce 42 42 Rate set_pte get_pte set_reduce get_reduce set_for get_for set_pte 196495/s -- -0% -15% -19% -29% -68% get_pte 197284/s 0% -- -15% -19% -28% -68% set_reduce 231848/s 18% 18% -- -5% -16% -62% get_reduce 242811/s 24% 23% 5% -- -12% -60% set_for 275692/s 40% 40% 19% 14% -- -55% get_for 607350/s 209% 208% 162% 150% 120% -- #!/usr/bin/perl use strict; use warnings; use List::Util; use Benchmark; sub pointer_to_element { local ($a, $b); return List::Util::reduce(sub { \($$a->{$b}) }, \shift, @_); } my %h; my %subs = ( set_pte => sub { my $ref = pointer_to_element(\%h, qw<foo bar baz>); return $$ref = 42; }, get_pte => sub { my $ref = pointer_to_element(\%h, qw<foo bar baz>); return $$ref; }, set_reduce => sub { my $ref = List::Util::reduce(sub {\($$a->{$b}) }, \(\%h), qw<foo bar baz>); return $$ref = 42; }, get_reduce => sub { my $ref = List::Util::reduce(sub {\($$a->{$b}) }, \(\%h), qw<foo bar baz>); return $$ref; }, set_for => sub { my $ref = \%h; $ref = $ref->{$_} = {} for qw<foo bar>; return $ref->{baz} = 42; }, get_for => sub { my $ref = \%h; $ref = $ref->{$_} for qw<foo bar>; return $ref->{baz}; }, ); for my $sub (sort keys %subs) { print "$sub "; %h = (); if ($sub =~ /^get/) { my $val = $subs{$sub}->(); print exists $h{foo}{bar}{baz} ? "did " : "didn't ", "autovivify "; $h{foo}{bar}{baz} = 42 } $subs{$sub}->(); print $subs{$sub}->(), " $h{foo}{bar}{baz}\n"; } Benchmark::cmpthese(-1, \%subs); snip > And if you want better answers to questions, use monks. > Not sure why these mailing lists exist, anyway! snip Well, this mailing list exists specifically because all of the alternatives (Perl Monks, c.l.p.m, c.l.p, etc.) were/are seen as being hostile to new users. I admit that this list has started to degenerate (and I am just as guilty as anyone else). Perhaps it is time to start sending out the FAQ again (I have been meaning to, but Real Life(tm) interfered). If anyone has any updates for the FAQ, let me know. -- Chas. Owens wonkden.net The most important skill a programmer can have is the ability to read. -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/