First, I would like to say that MinimalBy
(in the answers by @Mr. Wizard/@UnchartedWorks) is the cleanest way to solve the problem. It's too bad it's not optimized for arrays.
A small adjustment @MikeY's use of Ordering
results in a tremendous performance improvement. I made a reference to it in a comment, but it seems it has not been appreciated in the way I expected. So I will demonstrate. Ordering[x, 1]
is a special, optimized case that returns the position of the minimalelementminimal element in x
.
SeedRandom[2]
v = RandomInteger[10^9, {10^7, 2}];
v[[v[[All, 2]] ~Ordering~ 1]] // AbsoluteTiming
MinimalBy[v, Last] // AbsoluteTiming (* Mr. Wizard, UnchartedWorks)
v[[Ordering[v[[All, 2]]] // First]] // AbsoluteTiming (* another tweak of MikeY's *)
v[[Ordering[v[[All, 2]]]]] // First // AbsoluteTiming (* MikeY *)
(*
{0.188194, {{497087695, 12}}}
{0.452981, {{497087695, 12}}}
{2.19028, {497087695, 12}}
{2.52904, {497087695, 12}}
*)
Note: Ordering[x, -1]
is also a special optimized case returnthat returns the position of the maximal element of x
. Other cases of Ordering
compute the complete ordering, which takes considerably longer. Ordering
has been used this wayin these ways in many answers on the site.
Ordering[v[[All, 2]], 1] // AbsoluteTiming (* min position *)
Ordering[v[[All, 2]], -1] // AbsoluteTiming (* max position *)
Ordering[v[[All, 2]]] // First // AbsoluteTiming (* min position from complete ordering *)
Ordering[v[[All, 2]], {2}] // AbsoluteTiming (* 2nd smallest position *)
Ordering[v[[All, 2]], 2] // AbsoluteTiming (* two smallest positions *)
(*
{0.188538, {8647676}}
{0.194112, {323408}}
{2.15685, 8647676}
{2.16561, {8296548}}
{2.16896, {8647676, 8296548}}
*)