1

I have matrix A and a vector b, which specifies column index of the element to be extracted for each corresponding row of the matrix.

For example,

A = [1 2 3
     4 5 6
     7 8 9]

b = [1 3 2]'

I'd like to have c = [1 6 8]' on output. How to achieve this?

I tried A(:, b), but it doesn't work as I need.

Mohsen Nosratinia
  • 9,844
  • 1
  • 27
  • 52
user979454
  • 11
  • 1
  • possible duplicate of [MATLAB indexing question](http://stackoverflow.com/questions/4842512/matlab-indexing-question) – Amro Oct 14 '11 at 04:14

2 Answers2

2

There may be a more elegant solution, but this works:

b = [1 3 2]';
[rows, cols] = size(A);
A(sub2ind([rows cols], [1 : rows]', b))
dantswain
  • 5,427
  • 1
  • 29
  • 37
  • Avoid using `[]` when you mean `()` because it'll cause unnecessary calls to `horzcat` and `vertcat` (I expect). – Nzbuu Oct 11 '11 at 09:42
  • Interesting. I always think of `[]` as "whatever's in here is an array". I know that's not the technical truth, but it's what I think when I'm reading/writing code. I assume that you mean that `[1 : rows]'` could be `(1 : rows)'`. In my (admittedly flawed) mental model of what's going on, I'm saying "I want a column vector from 1 to rows." Seems like the order of operations would be such that there would be no calls to horzcat there? I.e., we get something like `temp1 = 1 : rows`, `temp2 = [temp1]` (no horzcat b/c there's only one object), `temp3 = temp2'`. – dantswain Oct 11 '11 at 13:45
  • 2
    TBH, I'm not sure how clever the MATLAB parser is in this case. Certainly if you have an object, `o`, and you write `[o]`, then it will call the `horzcat` and `vertcat` methods. Also, it's generally worth following the M-Lint advice regardless. – Nzbuu Oct 11 '11 at 19:08
  • 1
    Old habits die hard :) I was really curious about this, so I did a little profiling. I wrote three functions calculating: `[1 : 10].'`, `(1 : 10).'`, and `[(1 : 10).']`. I ran the profiler on a script that called each function 100,000 times. `[(1 : 10).']` was actually consistently the fastest by about 0.1 sec.(?!) Obviously this is not at all rigorous, but *for me* the moral of the story is that the readability of `[1 : N]` is worth the tiny performance hit (at least for N reasonably small). Speaking only on behalf of myself, of course. – dantswain Oct 11 '11 at 19:45
2

As an alternative to @dantswain's solution, you can go to the linear indices directly, assuming you're always selecting from the columns:

r = size(A,1);
A( (1:r).' + (b-1) * r)

This will be faster, but not necessarily clearer.

Unfortunately, there isn't an elegant solution.

Nzbuu
  • 5,241
  • 1
  • 29
  • 51