I have an oddly shaped array (it is 100 by 100 by {1 or 3}, with the 1 or 3 being essentially random). I want to run a 'Do' loop on the first 2 dimensions of the array, but I only want to do the thing in the loop when I am at a member with three members in the last dimension. Is there a way to do this? I tried playing with things like If[Array[[i]][[j]][[3]]!=Null,t,f], but to no avail. At the end of the day, what I want is a way to write the following in Mathematica's language:

  • If Array[[i]][[j]][[3]] exists, then do expr

Looking forward to any solutions/advice/ideas.

  • $\begingroup$ In you If expression test on Length or Dimension. $\endgroup$
    – m_goldberg
    Commented Aug 15, 2017 at 18:59

2 Answers 2

Clear[f, fakef]
fakeData = Array[Range[RandomChoice[{1, 3}]] &, {10, 10}];
fakef = If[1 == Length[#], #, {Last[#]}] &;
Map[fakef, fakeData, {2}]

Since your question mentions a Do loop over your matrix, (not a Table or Map), I'll first assume you're not building a new matrix, you don't care at all about your single-element data, but you actually really care about the positions of the 3-element-stuff within your structure as well as the 3-element-stuff.

If you don't care about the positions and you're just looking to make a new matrix with your 3-element stuff modified, then as Alan says you can just Map your function at level {2} over your data with a conditional.

First I'll make some stuff;

stuff =  Table[  
  If[RandomReal[{0, 1}] < .01, {a[i, j], b[i, j], c[i, j]}, d], {i, 
     1, 100}, {j, 1, 100}];

If you really care about the positions in your matrix, i.e. you want to do something to the 3-element stuff, and you need to know where it came from, but you don't need to make a new matrix:

locationsOfLength3 = 
  Select[Position[stuff, x_ /; Length[x] === 3], Length[#] === 2 &];

Do[ somethingWithStuff[ stuff[[p[[1]], p[[2]]]] , p ], 

Note: I'm passing the location to my function as well as what was in stuff at that location. If you don't need the location, and don't need a matrix, you can ignore that bit.

If you need a matrix, but your function somethingWithStuff also needs to know where in your matrix the 3-element-stuff came from, you can do it with MapIndexed:

 newMatrix=MapIndexed[  If[Length[#] === 1, #, 
          somethingWithStuff[#, #2]] &, stuff, {2}];

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.