Recently, I was refactoring a CGI script at work. It contained a subroutine used to determine the default value for a dropdown list:
sub DefaultHashValue { my %h = @_; my %r = reverse %h; my @k = sort values %h; return $r{ $k[0] } }

Neat and short, I thought. But wait, what exactly does it do? We pick up the asciibetically first value and find the corresponding key. It took me some time to understand it (yes, I'm tough). Could this code be written in a more speaking way?

I'd probably write it differently:

sub sort_keys { my %h = @_; my @s = sort { $h{$a} cmp $h{$b} } keys %h; return $s[0] }

Our dropdowns vary in size from 2 elements to several hundreds. For pure curiosity (there were no speed problems), I benchmarked the solutions (see below). Interestingly, for lists over 50 elements, the original solution was faster.

It wasn't so hard to come with a winner. It's still readable, too:

sub min { my %h = @_; my $min = (keys %h)[0]; $h{$_} lt $h{$min} and $min = $_ for keys %h; return $min }

Which solution would you use and why? Or, would you use something else? Why? (I stayed with the original).

For the interested, the full testing and benchmarking code:

#!/usr/bin/perl use warnings; use strict; use Test::More; use Benchmark qw{ cmpthese }; sub orig { my %h = @_; my %r = reverse %h; return $r{ (sort values %h)[0] } } sub Sort { my %h = @_; return (sort { $h{$a} cmp $h{$b} } keys %h)[0] } sub min { my %h = @_; my $min = (keys %h)[0]; $h{$_} lt $h{$min} and $min = $_ for keys %h; return $min } # TEST for my $t ( { a => 'A', b => 'B', c => 'C' }, { abc => 'ABC', def => 'ABC' , xyz => 'XYZ' }, { 1 .. 1_000}, { map int rand 100, 1 .. 1_000 }, ) { my $o = orig(%$t); is Sort(%$t), $o, "onleline-$o"; is min(%$t), $o, "min-$o"; } done_testing(); # BENCHMARK for my $size (10, 100, 1_000, 5E4, 1E6) { my %h = map int rand 100, 1 .. $size; cmpthese(0, { orig => sub { orig(%h) }, sort => sub { Sort(%h) }, min => sub { min(%h) }, }); }
لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

In reply to Default Dropdown Value by choroba

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.