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).
use List::Util 'max'; my $largest_val = max map { expensive_func($_) } @items;
my $largest_item = argmax { expensive_func($_) } @items;
my ($largest_item, $largest_val) = argmax { expensive_func($_) } @item +s;
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.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; }
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: argmin & argmax
by Roy Johnson (Monsignor) on May 04, 2005 at 03:42 UTC | |
Re: argmin & argmax
by ikegami (Patriarch) on May 13, 2025 at 00:01 UTC | |
by sleet (Monk) on May 13, 2025 at 02:13 UTC | |
by ikegami (Patriarch) on May 13, 2025 at 04:45 UTC | |
Re: argmin & argmax
by eritain (Novice) on May 11, 2025 at 04:03 UTC | |
by tybalt89 (Monsignor) on May 11, 2025 at 19:21 UTC | |
by jdporter (Paladin) on May 12, 2025 at 14:43 UTC |