Reputation: 2299
Consider the matrix A
in Matlab of dimension fxmxm
, e.g. with f=4
and m=3
A(:,:,1)=[1 2 3; 4 5 6; 7 8 9; 10 11 12]
A(:,:,2)=[0.5 2 -1; 3 -1 0; 7 -5 8; 10 11 12]
A(:,:,3)=[-2 2 -2; 2 -2 -1; 7 -5 -3; 10 -2 0]
The characteristic of A
is the following: consider the vector 1xm
[A(i,j,1) A(i,j,2) ... A(i,j,m)]
. We have that A(i,j,1)>=A(i,j,2)>=...>=A(i,j,m)
. This holds for any i,j
with i=1,...,f
and j=1,...,m
.
Without using loops, I want to construct the matrix B
of dimension fxm
such that B(i,j)
gives the index of the first negative element in [A(i,j,1) A(i,j,2) ... A(i,j,m)]
. If there are no negative elements in [A(i,j,1) A(i,j,2) ... A(i,j,m)]
, B(i,j)
should be equal to m+1
.
In the example above
B=[3 4 2; 4 2 3; 4 2 3; 4 3 4]
Upvotes: 1
Views: 109
Reputation: 112769
You can use the two-output form of max
to act as “find
along a given dimension”, as follows:
[v, B] = max(A<0, [], 3);
B(~v) = size(A,3)+1;
Upvotes: 1
Reputation: 104565
You can approach this using a combination of find
, ind2sub
and accumarray
.
We can determine the row, column and slice locations for each of the values that are negative with find
and ind2sub
, take the row and column locations which will act as groups and will serve as our input key into accumarray
and use the slice locations that are negative as the value associated with each key. For each of the unique row and column locations, we determine the slice number that was negative that is the smallest. The result will be a matrix where each location will tell you the first slice that was negative.
However, for those 3D columns that aren't negative, what accumarray
will do is set these locations to 0. With the resulting matrix, any values that are 0, set them to m+1
:
ind = find(A < 0);
[rows, cols, slices] = ind2sub(size(A), ind);
B = accumarray([rows cols], slices, [size(A,1), size(A,2)], @min);
B(B == 0) = size(A,3) + 1;
For your example, we get:
B =
3 4 2
4 2 3
4 2 3
4 3 4
Upvotes: 2