Skip to main content
Fixed typos
Source Link
Michael E2
  • 245k
  • 18
  • 351
  • 775

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}}
*)

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 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 minimalelement 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 return the position of the maximal element of x. Other cases compute the complete ordering, which takes considerably longer. Ordering has been used this way 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}}
*)

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 minimal 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 that 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 in 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}}
*)
Source Link
Michael E2
  • 245k
  • 18
  • 351
  • 775

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 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 minimalelement 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 return the position of the maximal element of x. Other cases compute the complete ordering, which takes considerably longer. Ordering has been used this way 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}}
*)