How do I find the elements in a list that return the highest value for a function?
Update 2017
Mathematica 10 introduced MaximalBy
, becoming the canonical method.
MaximalBy[{{1, 2, 3}, {10}, {6, 2}, {3, 7}}, Total]
{{10}, {3, 7}}
It is fast as shown in the updated timings below.
If I understand the question this should be fastest:
listMaxArg[f_, L_List] := L ~Extract~ Ordering[f /@ L, -1]
listMaxArg[Total, {{1, 2, 3}, {10}}]
{10}
You could also find the top n
values by using -n
as the second argument to Ordering
.
This could be included in the function, e.g. listMaxArg[f_, L_List, n_Integer] := . . .
This method should be fast for finding multiple maximum values:
listMaxArg[f_, L_List] := L ~Extract~ Position[#, Max@#] &[f /@ L]
listMaxArg[Total, {{1, 2, 3}, {10}, {6, 2}, {3, 7}}]
{{10}, {3, 7}}
I argue the superiority of the Extract
-Position
method (from Arnoud Buzing) over Select
on the basis of timings. I will use Tr
in the place of Total
as it is faster on Packed Arrays, and therefore better shows the overhead of each method.
listMaxArgRM[f_, list_] :=
With[{max = f /@ list // Max}, Select[list, f@# == max &]]
listMaxArgMrW[f_, L_List] :=
L ~Extract~ Position[#, Max@#] &[f /@ L]
SeedRandom[1]
list = RandomInteger[7, #] & /@ RandomInteger[{1, 5}, 1000000];
r1 = listMaxArgRM[Tr, list]; // RepeatedTiming
r2 = listMaxArgMrW[Tr, list]; // RepeatedTiming
r3 = MaximalBy[list, Tr]; // RepeatedTiming
r1 === r2 === r3
{0.77, Null} {0.219, Null} {0.191, Null} True
While using Ordering
as in Mr.Wizard's answer will most likely be the fastest non-compiled solution, it will not return all possible arguments that maximize the return value. Here's a simple way of writing a function that does this:
listMaxArg[f_, list_] := With[{max = f /@ list // Max}, Select[list, f@# == max &]]
Here's an example that compares the two solutions:
a = {{1, 2, 3}, {10}, {6, 4}};
listMaxArg[Total, a]
(* Out[1]= {{10}, {6, 4}} *)
listMaxArgMrWiz[Total, a]
(*Out[2]= {{6, 4}} *)