There is a list in the form {a,b}, where the list is the numerical solution of some equation; List=Table[z[i]]. I need the "a" when "b" is minimal in the list.
5 Answers
Have you seen MinimalBy
?
SeedRandom[2]
v = RandomInteger[99, {7, 2}]
MinimalBy[v, Last]
{{92, 57}, {22, 84}, {63, 1}, {81, 96}, {19, 38}, {67, 68}, {63, 39}} {{63, 1}}
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}}
*)
Made up list
lst = Table[RandomInteger[100, 2], {10}]
lst={{24, 100}, {2, 30}, {93, 26}, {37, 86}, {66, 71}, {92, 27}, {94, 25}, {16, 39}, {30, 68}, {65, 98}}
Pick off the element you want by ordering the list based on second column
lst[[Ordering[lst[[All, 2]]]]] // First
{94, 25}
Pick off just element 'a'
lst[[Ordering[lst[[All, 2]]]]] // First// First
94
-
$\begingroup$ Have you seen the form
Ordering[lst[[All, 2]], 1]
? $\endgroup$ Commented May 18, 2017 at 16:02 -
$\begingroup$ @Michael E2, definitely more terse $\endgroup$– MikeYCommented May 18, 2017 at 16:33
-
$\begingroup$ And faster when put inside
lst[[..]]
-- no reordering of the list. $\endgroup$ Commented May 18, 2017 at 18:58
In:
SeedRandom[1];
xss = Table[RandomInteger[100, 2], {10}]
First @@ MinimalBy[xss, Last]
Out:
{{80, 14}, {0, 67}, {3, 65}, {100, 23}, {97, 68}, {74, 15}, {24,
4}, {100, 90}, {83, 70}, {1, 30}}
24
SeedRandom[2];
v = RandomInteger[99, {7, 2}];
First@SortBy[v, Last]
(* {63, 1} *)
also
Extract[#, Position[#[[All, 2]], Min[#[[All, 2]]]]] &@v
SortBy[list, Last][[1,1]]
$\endgroup$