-2

I have a M x N x O matrix and I would like to reduce it to a MxN matrix in MATLAB using a vector b of size M that contains the index of the element in the third dimension that is to be kept.

What it does then is build a 2d array with its entries selected from various pages of the original 3d array.

I have this loop but I am interested in a loopless solution.

for i = 1:M
    for j = 1:N
        tmp(i, j) = P(i, j, b(i));
    end
end
Xaser
  • 2,066
  • 2
  • 22
  • 45
  • 1
    You could just remove the `j` loop altogether and replace `j` with `:` and it would do the same thing, right? – beaker Dec 19 '16 at 00:29
  • @beaker yes, good thinking. However do you see any way to do this completely loopless? – Xaser Dec 19 '16 at 01:02
  • Yes, I can give you a way to do it with `ndgrid` and `sub2ind`. I don't know how much that will buy you, but if you're interested I can post it. – beaker Dec 19 '16 at 01:07

1 Answers1

4

The easiest way may just be to remove the j loop in your code:

for ii = 1:M
    tmp(ii, :) = P(ii, :, b(ii));
end

But for the sake of comparison, here's a solution without a loop.


Given a 3d array P:

M = 7;
N = 5;
O = 6;
P = ones(M, N, O) .* permute(1:O, [3 1 2]);

(in this case I've used a 3d array where each element is equal to its O index)
and b, of size Mx1 with values from 1..O:

b = randi(O, M, 1)

you can construct the subscripts of all of the elements of P(:,:,1) and use b to select which plane to use:

[rr, cc] = ndgrid(1:M, 1:N);
inds = sub2ind(size(P), rr(:), cc(:), b(rr(:)));
tmp = reshape(P(inds), M, N)

For:

b.' =    5   4   1   5   3   1   3

we get:

tmp =

   5   5   5   5   5
   4   4   4   4   4
   1   1   1   1   1
   5   5   5   5   5
   3   3   3   3   3
   1   1   1   1   1
   3   3   3   3   3

The elements of each row corresponds to the element in b as expected.

beaker
  • 16,331
  • 3
  • 32
  • 49