in reply to Re (tilly) 3: How to pass a variable to function selected from a hash
in thread How to pass a variable to function selected from a hash
print join ",", map { &{$field_info{$_}{format}}($deal) } @fields;
I had no idea where to begin. I couldn't see anything wrong at first. Thankfully, you're post, and the subject at hand, gave enough information that I could infer/guess what the other data structures might look like. In order to optimize your code, I had to imagine & construct the code that wraps around it, in order to simulate it's environment.
After doing some simple code, I set to look at optimizations. Right away nothing jumped out at me. I thought about hash slices, not using map, using the arrow operator, replacing join with $, and more; some of them worked, others didn't.
Then, I remembered that we are looping over a set of deals. So I made an @deals array, and started to loop over it. Then I saw it. The map was taking the @fields, and was dereferencing the subref's each time through the @deals loop. Same thing each time through. Now, assuming that @fields is not modified in the loop, we can factor it out, and do it a single time outside of the @deals loop.
There are more optimizations I could make to my code, but I didn't want to stray too far from attempting to optimize Tilly's code, and loose the point of the excercise.
Anyhow, this is what I came up with:#!/usr/bin/perl -w use strict; #I am sure there are more fields than this my @fields = qw(a b); #Subroutines that return a value. I imagine #you had alot more processing in here, but #this is all make-believe =) my %field_info = ( a => { format => sub {return $_[0]->{deep}{inside}{a}} }, b => { format => sub {return $_[0]->{deep}{inside}{b}} }, ); #Had to simulate a reasonable amount of data, that could #potentially cause a slowdown #Let's make @ deals my @deals; for(my $i = 0; $i < 10000; $i++) { push @deals, { deep => { inside => { a => "a[$i]", b => "b[$i]"} } } +; } #Force commas to be the field seperator inside #print(), so we can drop the join(), and pass an array #to print, rather than one long "joined" string - it should be faster local $, = ','; #Set the output record seperator, so that each call to #print tags on a "\n" after printing out the $deal local $\ = "\n"; #Dereference the subroutines, so that we aren't doing a hash traversal #each time through the @deals loop AND the map. my @dereferenced_subs = map { $_->{format} } @field_info{ @fields }; #Print out each $deal foreach my $deal (@deals) { print map { $_->($deal) } @dereferenced_subs; }
How's that, did I miss anything?
Update: I found one optimization, although it could be at the expense of readability. The part where I dereference the subs before going into a loop, I changed to a hash slice to improve the speed of the hash lookup, if there was alot of fields this could make a larger difference. Also, I added a \n after each print, so that the information could be pretty printed.
|
---|
Replies are listed 'Best First'. | |
---|---|
Re (tilly) 5: How to pass a variable to function selected from a hash
by tilly (Archbishop) on Jan 18, 2001 at 13:10 UTC |