This is what I threw on my scratchpad, plus two bug fixes:
sub maxima(&@)
{
my $measure = shift @_;
return if ! @_;
my @maxima = shift @_;
my $max;
$max = $measure->( $_ ) for @maxima;
for( @_ ) {
my $key = $measure->( $_ );
if( $max < $key ) {
@maxima = $_;
$max = $key;
} elsif( $max == $key ) {
push @maxima, $_;
}
}
return @maxima;
}
sub minima(&@)
{
my $measure = shift @_;
return if ! @_;
my @minima = shift @_;
my $min;
$min = $measure->( $_ ) for @minima;
for( @_ ) {
my $key = $measure->( $_ );
if( $key < $min ) {
$min = $key;
@minima = $_;
} elsif( $key == $min ) {
push @minima, $_;
}
}
return @minima;
}
sub strmaxima(&@)
{
my $measure = shift @_;
return if ! @_;
my @maxima = shift @_;
my $max;
$max = $measure->( $_ ) for @maxima;
for( @_ ) {
my $key = $measure->( $_ );
if( $max lt $key ) {
@maxima = $_;
$max = $key;
} elsif( $max eq $key ) {
push @maxima, $_;
}
}
return @maxima;
}
sub strminima(&@)
{
my $measure = shift @_;
return if ! @_;
my @minima = shift @_;
my $min;
$min = $measure->( $_ ) for @minima;
for( @_ ) {
my $key = $measure->( $_ );
if( $key lt $min ) {
@minima = $_;
$min = $key;
} elsif( $key eq $min ) {
push @minima, $_;
}
}
return @minima;
}
Which I think would be fine additions to List::Util.
However, (Update: I added return if ! @_; to each because ) these should return an empty list not (undef) when given an empty list.