Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
Suppose you have a list of items, and you are going to compute some expensive function on each of them. Sometimes it is convenient to have the minimum (or maximum) value of the function. Other times, it is more convenient to have the item which minimizes (or maximizes) the function (for example, what is the hash key that corresponds to the largest hash value?). And sometimes you even want both.

The latter behavior is referred to as argmin and argmax. To do this in Perl, you can always sort based on the expensive function, and then grab the min/max, but the sort is very wasteful for long lists (even with a Schwartzian Transform). Instead, here's a simple watermarking way to do it. In list context, it also returns both values of interest (the item that minimized/maximized the function, and the min/max value itself).

  • Get the largest value that an expression takes on:
    use List::Util 'max'; my $largest_val = max map { expensive_func($_) } @items;
  • Get the item which produces the largest value on an expression:
    my $largest_item = argmax { expensive_func($_) } @items;
  • Get both at once:
    my ($largest_item, $largest_val) = argmax { expensive_func($_) } @item +s;
A very simple concept, but quite useful.
sub argmax(&@) { my $index = undef; my $max = undef; my $block = shift; for (@_) { my $val = $block->($_); if ( not defined $max or $val > $max ) { $max = $val; $index = $_; } } return wantarray ? ($index, $max) : $index; } sub argmin(&@) { my $index = undef; my $min = undef; my $block = shift; for (@_) { my $val = $block->($_); if ( not defined $min or $val < $min ) { $min = $val; $index = $_; } } return wantarray ? ($index, $min) : $index; }
These could also be implemented with List::Util::reduce, but just doing it by hand makes it easier to let the block to run with $_ aliased to the relevant value -- instead of fussing with $a and $b in L::U::reduce.

In reply to argmin & argmax by blokhead

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



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (2)
As of 2024-04-16 20:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found