3
$\begingroup$

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!

$\endgroup$
1
  • 2
    $\begingroup$ "its" - possessive, not "it's" (title) $\endgroup$ Commented Jul 17, 2012 at 4:35

3 Answers 3

5
$\begingroup$

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
$\endgroup$
1
  • $\begingroup$ Very elegant solution! Thank you! $\endgroup$ Commented Jul 17, 2012 at 3:00
6
$\begingroup$
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]
$\endgroup$
3
  • $\begingroup$ I'm unable to produce the example solution, but certainly have learned some new tricks here. Thanks! $\endgroup$ Commented Jul 17, 2012 at 3:03
  • $\begingroup$ @RHall, did you remember to ClearAll@f after running RMs solution, before trying mine? $\endgroup$
    – Rojo
    Commented Jul 17, 2012 at 3:55
  • $\begingroup$ I ran yours first on a clean kernel. Certainly a good solution. Thanks very much! $\endgroup$ Commented Jul 17, 2012 at 11:25
0
$\begingroup$

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}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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