Click here to get back home

advice on good perl idiom

 HomeNewsGroups | Search | About
 comp.lang.perl.misc    Post an article   get this group's latest topics as an RSS feed add this group's latest topics to your My MSN content add this group's latest topics to your My Yahoo content
Subject Author Date
advice on good perl idiom Mike Hunter 06-03-2008
Posted by Mike Hunter on June 3, 2008, 11:08 am
Please log in for more thread options
Hey folks,

Recently I was coding and wanted to see which of 4 strings had the
largest result when passed to a function. This is what I ened up
writing:

while (...)
{

my @roundArr;
push @roundArr, [$A, check($goodPrefix.$A)];
push @roundArr, [$C, check($goodPrefix.$C)];
push @roundArr, [$T, check($goodPrefix.$T)];
push @roundArr, [$G, check($goodPrefix.$G)];

@roundArr = sort {$b->[1] <=> $a->[1]} @roundArr;
print $roundArr[0]->[0]." wins!\n";

}

The code works fine, but I can't help but think there's a better idiom
for what I'm trying to do. I get a little bit of a creepy feeling by
using an array, I feel like I should be doing something with a hash. I
guess there's no way of getting around having to associate the given
check() result with the particular input.

Any thoughts on some awesome one-liner that I can't see?

Thanks,

Mike

Posted by A. Sinan Unur on June 3, 2008, 11:53 am
Please log in for more thread options

> Recently I was coding and wanted to see which of 4 strings had the
> largest result when passed to a function. This is what I ened up
> writing:
>
> while (...)
> {
>
> my @roundArr;
> push @roundArr, [$A, check($goodPrefix.$A)];
> push @roundArr, [$C, check($goodPrefix.$C)];
> push @roundArr, [$T, check($goodPrefix.$T)];
> push @roundArr, [$G, check($goodPrefix.$G)];
>
> @roundArr = sort {$b->[1] <=> $a->[1]} @roundArr;
> print $roundArr[0]->[0]." wins!\n";
>
> }

I don't know about idioms but the question is do you need to store the
results to the check call? If not:

#!/usr/bin/perl

my $goodPrefix = 'prefix';
my ( $A, $C, $T, $G ) = ('a', 'cc', 'ttt', 'gg' );

my $winner = $A;
my $winner_score = check( $goodPrefix.$A );

for my $s ( $C, $T, $G ) {
my $score = check( $goodPrefix.$s );
if ( $score > $winner_score ) {
$winner = $s;
$winner_score = $score;
}
}

print "$winner\t$winner_score\n";

sub check { length shift }

__END__

If you absolutely must use a hash:

#!/usr/bin/perl

use strict;
use warnings;

my $goodPrefix = 'prefix';

my ( $A, $C, $T, $G ) = ('a', 'cc', 'ttt', 'gg' );

my %scores = map { $_ => check( $goodPrefix.$_ ) } ( $A, $C, $T, $G );

my $winner = (sort { $scores <=> $scores } keys %scores)[0];

print "$winner\t$scores\n";

sub check { length shift }

__END__

> Any thoughts on some awesome one-liner that I can't see?

If you have a large number of elements, sort is going to do far more
comparisons than simply walking the elements.

Sinan

--
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/

Posted by Ben Morrow on June 3, 2008, 12:20 pm
Please log in for more thread options

>
> If you absolutely must use a hash:
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
>
> my $goodPrefix = 'prefix';
>
> my ( $A, $C, $T, $G ) = ('a', 'cc', 'ttt', 'gg' );
>
> my %scores = map { $_ => check( $goodPrefix.$_ ) } ( $A, $C, $T, $G );
>
> my $winner = (sort { $scores <=> $scores } keys %scores)[0];
>
> print "$winner\t$scores\n";
>
> sub check { length shift }

The hash needs to be the other way round:

use List::Util qw/max/;

my %scores = map { check("$goodPrefix$_") => $_ } qw/a cc ttt gg/;
my $winner = max keys %scores;
print "$scores\t$winner\n";

If there is a tie this will pick the last from your original list.

Ben

--
BEGIN;local($#,$;,$/)=@_;for(keys%{ #ben@morrow.me.uk
$#});/(\w):/&&(&(($#.$_,$;.$+,$/),next);$/==$*&&&)($;.$
_)}};*_=sub{for(@_){$|=(!$|||$_||&)(q) )));&((q:\:\::,q,,,$_);$_&&&)("\n")}}}_
$J::u::s::t, $a::n::o::t::h::e::r, $P::e::r::l, $h::a::c::k::e::r, $,

Posted by Jürgen Exner on June 3, 2008, 11:59 am
Please log in for more thread options
>Hey folks,
>
>Recently I was coding and wanted to see which of 4 strings had the
>largest result when passed to a function. This is what I ened up
>writing:
>
>while (...)
>{
>
> my @roundArr;
> push @roundArr, [$A, check($goodPrefix.$A)];
> push @roundArr, [$C, check($goodPrefix.$C)];
> push @roundArr, [$T, check($goodPrefix.$T)];
> push @roundArr, [$G, check($goodPrefix.$G)];

Ouch! Replace the preceeding 4 lines with
        for ($A, $C, $T, $G) {
                 push @roundArr, [$_, check($goodPrefix.$_)];
        }

>
> @roundArr = sort {$b->[1] <=> $a->[1]} @roundArr;
> print $roundArr[0]->[0]." wins!\n";
>
>}
>
>The code works fine, but I can't help but think there's a better idiom
>for what I'm trying to do.

Conceptually you just loop through the data set and remember, which
element produced the best result so far:
        $best = $a; #just as the default start value
        for ($b, $c, $d) {
                $best = $_ if check($_) > check($best)
        }

However this has some redundancies like computing $best over and over
again. Therefore you want to store that result in an auxiliary variable
$bestV:

        $best = $a; #just as the default start value
        $bestV = check ($a);
        for ($b, $c, $d) {
                if (($tmp = check($_)) > $bestV) {
                        $best = $_;
                        $bestV = $tmp;
                }
        }

>I get a little bit of a creepy feeling by
>using an array, I feel like I should be doing something with a hash. I
>guess there's no way of getting around having to associate the given
>check() result with the particular input.

The point is that you don't need to keep all of the temporary results
around, neither in a hash nor in an array. All you need to store is the
currently best candidate and for optimization its value.

jue

Posted by Tad J McClellan on June 3, 2008, 9:25 pm
Please log in for more thread options

>>Recently I was coding and wanted to see which of 4 strings had the
>>largest result when passed to a function.


> Conceptually you just loop through the data set and remember, which
> element produced the best result so far:


That is known as the "high water mark" algorithm.


--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher0cmdat/"

Similar ThreadsPosted
Good documentation or good source examples for Image::Magick or converter from commandline to perl April 1, 2008, 5:23 pm
Good morning or good evening depending upon your location. I want to ask you the most important question of your life. Your joy or sorrow for all eternity depends upon your answer. The question is: Are you saved? It is not a question of how good you are, April 21, 2005, 1:25 pm
Good morning or good evening depending upon your location. I want to ask you the most important question of your life. Your joy or sorrow for all eternity depends upon your answer. The question is: Are you saved? It is not a question of how good you are, April 22, 2005, 3:33 pm
Good morning or good evening depending upon your location. I want to ask you the most important question of your life. Your joy or sorrow for all eternity depends upon your answer. The question is: Are you saved? It is not a question of how good you are, April 24, 2005, 6:50 pm
Good morning or good evening depending upon your location. I want to ask you the most important question of your life. Your joy or sorrow for all eternity depends upon your answer. The question is: Are you saved? It is not a question of how good you are, May 1, 2005, 11:27 am
Perl/regex Advice August 5, 2004, 4:42 pm
advice for a gui for my perl scripts. April 29, 2005, 11:37 am
Acceptible idiom ? October 11, 2004, 12:36 pm
Concise idiom sought March 25, 2006, 9:14 am
idiom for managing passed arguments? October 18, 2005, 12:03 pm

Our other projects:

Art Dolls, Fairies and Mermaids - Sunnyfaces.net

Roy's Linux, Programming and Search Engines messages

1-Script XML SitemapXML Sitemap