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.

In the example code below we have a list of triples that produce one or more sublists with at least one zero value. How can the positions of the lowest non zero value in each sublist be returned where that condition applies, and identify those sublists whose lowest value is zero so that the overall positions of the non-zero values can be obtained, and not lose their positions in the overall list?

 In[1]= myList=Partition[RandomSample[Range[0, 8], 9], 3]
 Out[1]= {{3, 1, 8}, {5, 0, 2}, {7, 6, 4}}

What I would like to get returned is something like this: {2,z,3} for the above list. Thanks for the help!

share|improve this question
2  
"its" - possessive, not "it's" (title) –  alancalvitti Jul 17 '12 at 4:35
    
+1 for the english lesson ;) –  R Hall Jul 18 '12 at 0:17

3 Answers 3

up vote 5 down vote accepted

You could also use Position instead of Ordering so that the positions of all the lowest values in each sublist can be found:

Clear@f
f[l_List] /; Min@l != 0 := Flatten@Position[#, Min@#] &@l
f[_] := z

For example:

myList = {{2, 0, 5, 0}, {1, 4, 8, 1}, {7, 2, 6, 3}};
f /@ myList
(* {z, {1, 4}, {2}} *)

A simpler way of writing the same would be:

Clear@g
g[l_List] := With[{m = Min@#}, If[m === 0, z, Flatten@Position[#, m]]] &@l
share|improve this answer
    
Very elegant solution! Thank you! –  R Hall Jul 17 '12 at 3:00
f[l_List] := With[{minPos = First@Ordering[l, 1]}, minPos /; l[[minPos]] =!= 0];
f[_] := $Failed

You use it like f /@ myList

But what you ask isn't straightforward if what you say you want is what you want: that is, the overall minimmu of the non-zero values

Ordering[#, 1] & /@ (myList /. {0 -> Infinity}) 

Also, if you know that there are never negative values (if there's a zero, it will always be the minimum), you can discard those lists first

f[{___, 0, ___}] := $Failed
f[l_] := First@Ordering[l, 1]
share|improve this answer
    
I'm unable to produce the example solution, but certainly have learned some new tricks here. Thanks! –  R Hall Jul 17 '12 at 3:03
    
@RHall, did you remember to ClearAll@f after running RMs solution, before trying mine? –  Rojo Jul 17 '12 at 3:55
    
I ran yours first on a clean kernel. Certainly a good solution. Thanks very much! –  R Hall Jul 17 '12 at 11:25

An answer in the form of a function. Using Part and ReplaceAll help make the function clearer in my opinion. Read from the inside out. That's how the function was built. First I got the Map to work. Then wrapped it with a ReplaceAll (/.). Then extracted the desired column.

process[lis_] := 
 Part[
   ReplaceAll[
       Map[{Ordering[#, 1][[1]], Min[#]} & , lis],
       {_, 0} -> {"z", 0}
   ],(* ReplaceAll *)
  All, 1
  ] (* Part *)

and then

test = {{3, 1, 8}, {5, 0, 2}, {7, 6, 4}};
process[test]

gives

{2, "z", 3}
share|improve this answer

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.