7
$\begingroup$

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!

$\endgroup$
  • 1
    $\begingroup$ You'll need SortBy and Part. $\endgroup$ – swish Aug 14 '16 at 23:51
  • $\begingroup$ 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! $\endgroup$ – Siav Josep Aug 15 '16 at 0:32
15
$\begingroup$
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}];

BenchmarkPlot

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

$\endgroup$
  • $\begingroup$ Great example using operator forms of MinimalBy and MaximalBy! $\endgroup$ – JungHwan Min Aug 15 '16 at 0:02
  • $\begingroup$ 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. $\endgroup$ – Karsten 7. Aug 16 '16 at 9:05
11
$\begingroup$

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}]]
$\endgroup$
  • $\begingroup$ i don't understand the last part of the third line. why does that-1 mean? $\endgroup$ – Alucard Aug 15 '16 at 2:04
  • 1
    $\begingroup$ @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. $\endgroup$ – Mr.Wizard Aug 15 '16 at 2:20
  • 1
    $\begingroup$ 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 $\endgroup$ – Alucard Aug 15 '16 at 2:38
  • 1
    $\begingroup$ 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.) $\endgroup$ – Karsten 7. Aug 15 '16 at 11:56
  • 1
    $\begingroup$ Or using {N@func@# &} instead of {N@*func}. $\endgroup$ – Karsten 7. Aug 15 '16 at 12:09

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.