# Finding the two pairs in a list of pairs that minimize and maximize a given function

I need to declare a list of ordered pairs, and with it I need to declare a function of two variables, say x and y, and print the ordered pairs giving the maximum and the minimum value on the function.

For example, suppose the list is

L = {{1, 2}, {5, 3}, {9, 2}}


and the function is

2 x + y


With {x, y} = {1, 2}, I will get 4 , with {5, 3}, 13, and with {9, 2}, 20 . Then I need to print {1, 2} and {9, 2} as the result.

Can anyone help me with it please? I don't know how to write it!

• You'll need SortBy and Part. Aug 14, 2016 at 23:51
• Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! Aug 15, 2016 at 0:32

list = {{1, 2}, {5, 3}, {9, 2}}
func = 2*#[[1]] + #[[2]] &;

Through[{MinimalBy[func], MaximalBy[func]}[list]]


{{{1, 2}}, {{9, 2}}}

Some Benchmarking:

benchMarkResults = Transpose@Table[
With[{riList = RandomInteger[{1, 9999999}, {Round[10^n], 2}], rn = Round[10^n]},
{{rn,
Through[{MinimalBy[func], MaximalBy[func]}[riList]]; // AbsoluteTiming // First},
{rn,
riList[[Ordering[func /@ riList][[{1, -1}]]]]; // AbsoluteTiming // First},
{rn, SortBy[riList, func][[{1, -1}]]; // AbsoluteTiming // First},
{rn,
SortBy[riList, {N[func@#] &}][[{1, -1}]]; // AbsoluteTiming // First},
{rn, SortBy[riList, {N@*func}][[{1, -1}]]; // AbsoluteTiming // First},
{rn,
Pick[riList, #, Alternatives @@ MinMax@#] &[Function[{x, y}, 2 x + y] @@@ riList];
// AbsoluteTiming // First}}],
{n, 0, 7, 0.2}];


The gray line indicates where SystemOptions["CompileOptions" -> {"MapCompileLength"}] kicks in.

• Great example using operator forms of MinimalBy and MaximalBy! Aug 15, 2016 at 0:02
• The Pick version should be understood as a template, where applying the function to the list is done in the last [ ]. For illustration purpose I chose a least optimal approach (applying the function to each individual pair) that scales linearly ("ApplyCompileLength" is Infinity). For better performance one can use Map (autocompiles), vectorized code, compiled code, parallelized code, or a combination of these. Aug 16, 2016 at 9:05

SortBy is useful. Taking Karsten's example input:

list = {{1, 2}, {5, 3}, {9, 2}};
func = 2*#[[1]] + #[[2]] &;

SortBy[list, func][[{1, -1}]]

{{1, 2}, {9, 2}}


To make this method robust one should convert the output to explicit numbers(1)(2) with N since e.g. Sort[{1, Pi, 5, 9}] evaluates to {1, 5, 9, π}. Also it is more efficient to use the stable sort syntax(1)(2)(3)(4)(5). Therefore what I should have written:

SortBy[list, {N@*func}][[{1, -1}]]


Or as Karsten7 points out, since Composition does not compile this is much faster on packable data:

SortBy[list, {N @ func @ # &}][[{1, -1}]]

• i don't understand the last part of the third line. why does that-1 mean? Aug 15, 2016 at 2:04
• @Alucard (Or should I say Dracula?) It is a Part specification for the last element in the list, i.e. the one that evaluated to the largest Integer. Aug 15, 2016 at 2:20
• Alucard is the son of Dracula in the castlevania lore, not dracula. Thanks for the info, so the position in a list can be even counted backward from the last element? i have just realized it manipulating your code Aug 15, 2016 at 2:38
• Using N@*func seems to break optimizations done by SortBy. (Using for example funcN = N[2*#[[1]] + #[[2]]] &; does not have such a negative impact on the performance.) Aug 15, 2016 at 11:56
• Or using {N@func@# &} instead of {N@*func}. Aug 15, 2016 at 12:09