3
$\begingroup$

I don't understand why this doesn't work:

In[30]:= MinimalBy[{{1, -Infinity}, {2, 3}}, Last]

Out[30]= {{2, 3}}

While this works seemingly:

In[31]:= MaximalBy[{"A" -> Infinity, "B" -> 2}, Last]

Out[31]= {"A" -> Infinity}
$\endgroup$
1
  • 1
    $\begingroup$ Others have explained well why this doesn't work, if you need a workaround you can use infConvert[x_]:=x/.{Infinity->$MaxMachineNumber,-Infinity->-$MaxMachineNumber} and then MinimalBy[{{1,-Infinity},{2,3}},Last[infConvert[#]]&] $\endgroup$ – N.J.Evans Sep 15 '15 at 17:30
4
$\begingroup$

I agree, that's certainly confusing! Jim explained why it happened. Now how do we fix it?

Before MinimalBy was introduced, I used

MinBy[list_, fun_] := list[[First@Ordering[fun /@ list, 1]]]

It does more or less the same thing except that it only returns a single result, even if there are multiple minimal elements.

Unlike MinimalBy, Ordering (and Sort) can take a custom comparison function. Let's include this:

MinBy[list_, fun_, less_] := list[[First@Ordering[fun /@ list, 1, less]]]

The default behaviour is

MinBy[{{1, -Infinity}, {2, 3}}, Last, OrderedQ[{##}] &]

(* {2,3} *)

We can instead use

MinBy[{{1, -Infinity}, {2, 3}}, Last, Less]

(* {1, -∞} *)

Using a custom comparison function will probably significantly impact performance, but I haven't measured by how much. So avoid doing this when it's not necessary, e.g. when you have a very large list of only numbers.


There is another consideration (see under Possible Issues in the documentation), which also explains why Less is not the default comparison.

To find out which of two expressions is larger may be computationally expensive and difficult, or Mathematica might not even be able to do it. Mathematica may need to compute BesselJ[0, 1] and BesselJ[1, 1] numerically to decide which is larger, and for some expressions this might be expensive. Or we might even be asking for a symbolic comparison like a^2 > a assuming a > 1.

$\endgroup$
5
$\begingroup$

The documentation for MinimalBy states

The maximal element is determined using OrderedQ, not numerical ordering.

Try

OrderedQ[{3, Pi, 4}]
OrderedQ[{3, N[Pi], 4}]

You'll get False for the first (meaning the elements are not in canonical order) and True for the second (meaning the elements are in canonical order).

$\endgroup$
1
  • $\begingroup$ I guess then the solution is through SortBy or Max+Transpose. $\endgroup$ – Al Guy Sep 15 '15 at 5:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.