views:

205

answers:

4

I want to get a vector of elements of a Matlab matrix at predefined locations. For example, I have the following

>> i = [1,2,3];
>> j = [1,3,4];
>> A = [1,2,3,4; 5,6,7,8; 9,10,11,12; 13,14,15,16]

A =

     1     2     3     4
     5     6     7     8
     9    10    11    12
    13    14    15    16

I want a vector that will give me the values of A at the locations correspongin to i,j. I tried

A(i,j)

ans =

     1     3     4
     5     7     8
     9    11    12

but this is not what I wanted. I want to get the following

>> [A(i(1),j(1)); A(i(2),j(2));A(i(3),j(3))]

ans =

     1
     7
    12

What is the matlab syntax for that? Please, avoid suggesting for loops or anything that is not in a vectorized form, as I need this to be done fast. Hopefully there will be some built-in function.

A: 

For now I'm using this:

>> diag(A(i,j))

ans =

     1
     7
    12
celil
While this WILL work, it is a poor choice in general, since it first creates a new 3x3 matrix in memory, then it throws most of that matrix into the bit bucket using the diag function. If your arrays and the list of points in (i,j) were at all large, then the diag trick would be quite inefficient.
woodchips
+2  A: 
A(sub2ind(size(A),i,j))

If you really crave speed, you might try making your own copy of sub2ind.m that strips out all the input-checking that that function does.

SCFrench
+4  A: 

to get it in the fastest way, use linear indexing:

A((j-1)*size(A,1)+i)

remember that MATLAB uses a column-major order.

Amro
A: 

To understand how to do this, it is best to understand how matlab stores its arrays. In the matrix:

i = [1,2,3];
j = [1,3,4];
A = [1,2,3,4; 5,6,7,8; 9,10,11,12; 13,14,15,16]

matlab stores the elements going DOWN the columns. So they actually reside in memory in the order:

{1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16}

You can actually index a 2-d array using a SINGLE index. This is why the sub2ind trick works. Since the elements that you want to get are the 1st, 10th and 15th elements, as stored in a column-wise ordering,

singleIndex = [1 10 15];
A(singleIndex)
ans =
     1     7    12

To confirm that sub2ind gave that index list, try it...

ind = sub2ind([4 4],i,j)
ind =
     1    10    15
woodchips

related questions