In fact, you can solve this with simple matrix multiplication.
result = M * (1:size(M, 2)).'; 3 1 2 1 3
This works by multiplying the M x 3 matrix by a 3 x 1 array, where 3x1 elements are simple [1; 2; 3]
[1; 2; 3]
[1; 2; 3]
. In short, for each row of M
multiplication by elements is performed using an array of 3 x 1. Only 1 in row M
will produce the result. Then the result of this multiplication by elements is summed up. Since you only have one “1” per row, the result will be the index of the column that contains this number.
So, for example, for the first row of M
element_wise_multiplication = [0 0 1] .* [1 2 3] [0, 0, 3] sum(element_wise_multiplication) 3
Update
Based on the solutions provided by @reyryeng and @Luis below, I decided to make a comparison to see how the characteristics of different methods are compared.
To set up the test matrix ( M
), I created the form matrix asked in the original question and changed the number of rows. Which column had 1 was randomly selected using randi([1 nCols], size(M, 1))
. Runtime was parsed using timeit
.
When you start using M
type double
(default is MATLAB) you get the following runtime.

If M
is logical
, then matrix multiplication takes a hit because it must be converted to a number type before matrix multiplication, while the other two improve performance a bit.

Here is the test code I used.
sizes = round(linspace(100, 100000, 100)); times = zeros(numel(sizes), 3); for k = 1:numel(sizes) M = generateM(sizes(k)); times(k,1) = timeit(@()M * (1:size(M, 2)).'); M = generateM(sizes(k)); times(k,2) = timeit(@()max(M, [], 2), 2); M = generateM(sizes(k)); times(k,3) = timeit(@()find(M.'), 2); end figure plot(range, times / 1000); legend({'Multiplication', 'Max', 'Find'}) xlabel('Number of rows in M') ylabel('Execution Time (ms)') function M = generateM(nRows) M = zeros(nRows, 3); col = randi([1 size(M, 2)], 1, size(M, 1)); M(sub2ind(size(M), 1:numel(col), col)) = 1; end