I need a function to find max element of a list according to some custom ordering function, assuming that the function implements a total order (elements being compared might not even be numbers). Unlike Sort
, the predefined Max
function does not accept a custom ordering function. A naïve solution would be to use Sort[list, p]〚1〛
, but this would unnecessarily sort the whole list, while I only need to find the first element.
I ended up defining
max[list_, p_] := list[[Ordering[list, 1, p][[1]] ]];
and it works fine from performance point of view. But I wonder if there is a more simple or natural way to do this task. Is there a predefined function solving this problem that I missed?
Answer
If your operation can be converted to a canonical ranking rather than a pairwise comparison then you can use MaximalBy
introduced in version 10.
If not a good approach to a single pass through a list is Fold
. Here is a function using that:
foldMax[list_, p_] := Fold[If[p[##], ##] &, list]
This proves to be faster in some cases than using Ordering
(in your function):
x = RandomReal[9, 5000000];
max[x, Less] // AbsoluteTiming
foldMax[x, Less] // AbsoluteTiming
{1.209069, 4.32482*10^-6}
{0.430025, 4.32482*10^-6}
Comments
Post a Comment