Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a nested list of {x,y,z} and I want to find out the values of x and y where z is minimum. I can write a nested For loop and do it

mya = {{0, 1, 10}, {1, 1, 20}, {0, 2, 5}, {1, 2, 15}}

For[i = 1, i <= Length[mya[[All, 3]]], i++, 
If[mya[[All, 3]][[i]] == Min[mya[[All, 3]]], Print[mya[[i]]]]]

I get the desired output:

{0, 2, 5}

I know this problem is simple, but if someone can tell me a more elegant way to do it, it will be helpful as I wanna do it for a very large list.

share|improve this question
    
Cases[mya, x_ /; x[[3]] == Min[mya[[All, 3]]]] is another option –  Nasser Feb 14 at 12:42
1  
@Nasser : I posted a similar answer. Concerning your solution, I thought the part Min[mya[[All, 3]]] is evaluated Length@mya times. It may be better to let it only evaluate once as I did. –  Yi Wang Feb 14 at 12:49
add comment

5 Answers 5

up vote 6 down vote accepted

I think @halirutan's answer is quite nice and clean. Nevertheless just give an alternative one:

findLastMin[mat_] := Cases[mat, {__, Min@mat[[All, -1]]}]

findLastMin[mya]

{{0, 2, 5}}

There is additional {...} outside the desired output by the OP, because if there are multiple equal minimal values, it returns them all.

share|improve this answer
add comment

How about using SortBy to sort your list by the last element and then take the first entry?

First[SortBy[mya, Last]]
(* {0, 2, 5} *)

A simple iterative approach to go through your list exactly once and remember the minimum element can be written as

Block[{min = First[mya]},
 Do[If[Last[min] > Last[elm], min = elm], {elm, Rest[mya]}];
 min
]

Although my tests showed that this is a bit slower (about 2 seconds for 10^7 elements) as the first approach.

An faster approach then the two above is to first extract the minimum of all z-values and then go through the list until you hit the first match

Block[{min = Min[Last[Transpose[mya]]]},
 Do[If[Last[elm] === min, Return[elm]], {elm,mya}]
]
share|improve this answer
    
Thanks. I was trying to do this with a list of 60,000 length and sort seems to work much faster than For loop!! –  MathBiolGuy Feb 14 at 12:31
    
Man, you are on a roll today :). This is my third upvote to your today's answers. Looks like you have some plot against Mr.Wizard :). –  Leonid Shifrin Feb 14 at 12:41
    
@LeonidShifrin For the last weeks I barely had time to look at the site and today I just took some minutes and found some nice questions. But thanks. –  halirutan Feb 14 at 12:46
add comment

An alternate solution using Fold:

Fold[If[Last[#2] < Last[#1], #2, #1] &, {0, 0, Infinity}, mya]

If the list is known to be non-empty, the following solution is faster:

Fold[If[Last[#2] < Last[#1], #2, #1] &, First[mya], Rest[mya]]
share|improve this answer
add comment

Thanks everyone for the reply. Didn't expect such an overwhelming response. I did a quick check on the speed of each of the solutions by making a random list of 2x10^7 elements and compared the timing (given in bold) using the 4 solutions given by Yi Wang, halirutan and sakra:

a = RandomInteger[1000, {2*10^7, 3}];

Method 1:

findLastMin[mat_] := Cases[mat, {__, Min@Last@Transpose@mat}]
findLastMin[a] // Timing

{8.020000, {{710, 337, 0}, {347, 509, 0}, <<19744>>, {609, 151, 0}, {553, 806, 0}}}

Method 2:

First[SortBy[a, Last]] // Timing

{18.216000, {0, 28, 0}}

Method 3:

Block[{min = Min[Last[Transpose[a]]]}, 
Do[If[Last[elm] === min, Return[elm]], {elm, a}]] // Timing

{2.536000, {710, 337, 0}}

Method 4:

Fold[If[Last[#2] < Last[#1], #2, #1] &, {0, 0, Infinity}, a] // Timing

{29.132000, {710, 337, 0}}

Method 1 gives all solutions and is fairly quick. Once again thanks for all the solutions.

share|improve this answer
add comment

Not very efficient, I suspect, but two other (related) possibilities:

#[[Position[Ordering@Ordering@#[[All, 3]], 1, 1, 1][[1, 1]]]] &@mya

=>

{0, 2, 5}

Pick[#, Ordering@Ordering@#[[All, 3]], 1] &@mya

=>

{{0, 2, 5}}

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.