I have a 3D logical array, for example:
A = randi([0 1],x,y,z);
where x,y,z are integers.
Is there a way to find the first true value a
Not a very straightforward one.
That is because there may not be a true
anywhere along the third dimension.
By the way, what you're doing may lead to an extremely hard to find bug. If it is the case that there is no true value somewhere, find
will return the empty matrix ([]
). And, assigning an empty matrix to something in MATLAB will delete that element from the array you're assigning to.
Meaning:
B(ix,iy)
will be deletedB
will shrink by 1 B
A
(and are thus now indexing beyond the boundary of B
), MATLAB will automatically grow the array B
to fit your assignment. You'll be none the wiser, but all the results are meaningless garbage.
Luckily, MATLAB throws a warning if you're doing that on arrays with dimension larger than 1, BUT, if you're using the same technique on vectors (e.g., B
is a vector), MATLAB will not warn you.
So, at the very least, do a check:
for ix = 1:x
for iy = 1:y
if any(A(ix,iy,:))
B(ix,iy) = find(A(ix,iy,:), 1, 'first');
end
end
end
Also note that any
can take a second argument specifying the dimension to "any
" over, meaning
any(A,3)
will return an x×y
array of logicals, containing true
if there is a true
in A
along its third dimension, and false
otherwise. This may help you prevent having to compute the indices explicitly (oftentimes, they are not really explicitly needed if you change paradigm).
Now, having said all that, you could use
[~, B] = max(A ~= 0, [], 3);
but you'd still have to do checks on all-zeros:
B(~any(A, 3)) = 0;
I'd say, the loop with the check is just so much more intuitive that it'd have my preference. However, the max
technique is about 7 times faster, so when properly documented (probably with the loop as part of the comment above it, as well as in an accompanying unit test), then well, why not.