Its been a few days over a year since I first posted this node, but I have come across a few more little things that I am moved to gab about. Hopefully I am not reinventing the wheel.
When for...push is too much
Let's start off by with strict, warnings, and a normal hash with some data in it, shall we?
use strict;
use warnings;
my %cbusers = (
'BrowserUk' => 28,
'GrandFather' => 23,
'CountZero' => 20,
'wfsp' => 19,
'ambrus' => 19,
'Khen1950fx' => 18,
'atcroft' => 17,
'ELISHEVA' => 17,
'jwkrahn' => 16,
'Krambambuli' => 11,
'Lady_Aleena' => 9,
'Excalibor' => 7,
'Voronich' => 7,
'Eliya' => 7,
'gnosti' => 7,
'AndyZaft' => 6,
'frodonl' => 1,
'im2' => 1,
);
Now that we have our data (even though it says it is mine, I will share it with you) which is from the current users in the Chatterbox, let's play.
for...push vs. map
One way to create a list with data from another source blended into it is to loop it and push the new strings into another array. You can then print the array with join.
my @cbusers_lines;
for my $user (sort keys %cbusers) {
push @cbusers_lines, "$user is a level $cbusers{$user} user";
}
print join( "\n" , @cbusers_lines );
Now that is all fine and well if you have another use for the list, however, if this is a once off deal, you might want to think about just using a map to get the job done. Though one shouldn't think of screen real estate, the following will help with that too.
print join( "\n" , map( "$_ is a level $cbusers{$_} user" , sort keys
+%cbusers ) );
This was a great idea shown to me by someone else a long time ago for which I am still grateful. And see that there is less typing for you? :)
for...push and List::Util::sum vs. +=
Now we come upon a problem I had a few weeks ago. I was pushing a lot of numbers into an array, and I ran out of memory! (see A script with a loop is running my computer Out of memory) I was really scrambling after that. How was I to add lots and lots and lots and lots of numbers together that were being generated on the fly? Like the match against map above, how often are you going to use the array you are creating? More than once, you may want to push it; only once, well I will show you.
my @cbusers_levels;
for my $user (keys %cbusers) {
push @cbusers_levels, $cbusers{$user};
}
print sum(@cbusers_levels);
In the above, you are storing the numbers in the array which is in memory. You are also calling in help from a module to add them all up. That might be okay for smaller lists, but even storing a list of all the levels of all the PerlMonks could slow down an older computer.
A simple solution would be to keep adding to a variable and just store one number that keeps growing like so...
my $cbusers_total_levels;
for my $user (keys %cbusers) {
$cbusers_total_levels += $cbusers{$user};
}
print "Total: $cbusers_total_levels\n";
print "Average: ".$cbusers_total_levels / scalar(keys %cbusers); #even
+ get the average w/o importing
Unlike the above (like it really matters), it doesn't save you real estate on the screen, but it could save your computer's memory from filling up.
In closing whenever I find I am pushing an array, I ask "Is this the only time I am going to use this array?" If the answer is yes; I will more than likely go to a map if I am inserting text into a string for another source, or I will use += if I just want to add up a bunch of numbers.
It is finding little things like this that makes Perl fun, and why I feel that Perl is a good game to play! (Well, not all the time, but most of it.)
Have a cookie and a very nice day!
Lady Aleena
|