# Built-ins for discrete ArgMax or ArgMin?

Wondering whether there are discrete versions of ArgMax / ArgMin, that is, something that will find the part of an expression at which some function f of the elements is maximized (or minimized).

Last[Ordering[f/@list]] and First[Ordering[f/@list]] will do, but the following does not work:

ArgMax[Function[i, (f/@list)[[i]]], i]

-
If you use Ordering, Ordering[list, 1] is more efficient than First@Ordering[list] –  Szabolcs Feb 11 '13 at 19:40

I guess Max and Min are the best fit for discrete lists.

f[x_] := x Sin[x];
list = RandomReal[10, 10^6];
(Position[#, Max[#], 2][[1, 1]]) &@(f /@ list)


One can forcefully use NArgMax or NArgMin for this purpose but they are likely to be extremely inefficient! One such example

list = RandomReal[10, 1000];
ob[i_?IntegerQ] := (f /@ list)[[i]];
ob@NArgMax[{Evaluate@ob[x],1<= x<= Length@list&&Element[x,Integers]},x]//AbsoluteTiming


{5.8344103, 7.91672}

Where as

Max[f /@ list]// AbsoluteTiming


{0., 7.91672}

For timing comparison with solution using Ordering see the following plot. Horizontal axes shows the data length of list and the vertical axes is denoting computation time in seconds. I have tested it in an Intel i7 PC with 64 GB RAM.

As one can see if you compile the functions you get even better speed ups.

cf=Compile[{{x,_Real,1}},
Module[{listval,max},
listval=# Sin[#]&/@x;
max=Max[listval];
(Position[listval,max])[[1,1]]
],
CompilationTarget->"C",
RuntimeAttributes->{Listable},Parallelization->True];

-
This seems to be much faster than the other proposal on large inputs. –  Reb.Cabin Feb 11 '13 at 16:15
Yes I will update the answer with timing comparison. –  PlatoManiac Feb 11 '13 at 16:16
Ordering[f /@ list, -1] for argmax and Ordering[f /@ list,1] for argmin seems to be faster than both Position-Max combination and Ordering[list,f[#1] < f[#2] &]. –  kguler Feb 11 '13 at 17:00

Ordering is good for this if you use a custom ordering function:

f=Sin;
list = RandomReal[{0, Pi}, 100];
First@Ordering[list, 1, f[#1] < f[#2] &]


And similarly for maximum replacing 1 with -1 (or < with >)

-
Manually supplying an ordering function seems to be much slower than just using Ordering[f/@list,1] as kguler recommended in a comment to an answer above. –  Wizard Oct 7 '13 at 21:59