11

For an arbitrary sized matrix x, how do I find the index of the last non-zero element in each row of a given matrix?

For example, for the matrix

x = [ 0 9 7 0 0 0; 5 0 0 6 0 3; 0 0 0 0 0 0; 8 0 4 2 1 0 ]

the vector [ 3 6 0 5 ] should be obtained.

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
Jack Lu
  • 115
  • 2
  • 5

4 Answers4

10

Here's a shorter version, combining find and accumarray

x = [ 0 9 7 0 0 0; 5 0 0 6 0 3; 0 0 0 0 0 0; 8 0 4 2 1 0 ];
%# get the row and column indices for x
[rowIdx,colIdx] = find(x);
%# with accumarray take the maximum column index for every row
v = accumarray(rowIdx,colIdx,[],@max)'
v =
     3   6   0   5
Jonas
  • 74,690
  • 10
  • 137
  • 177
4

Here's one version:

x = [ 0 9 7 0 0 0; 5 0 0 6 0 3; 0 0 0 0 0 0; 8 0 4 2 1 0 ];
c = arrayfun(@(k) find(x(k,:)~=0,1,'last'), 1:size(x,1), 'UniformOutput',false);
c( cellfun(@isempty,c) ) = {0};
v = cell2mat(c);

v =
     3     6     0     5

EDIT: Consider this alternative solution:

[m,v] = max( cumsum(x'~=0) );
v(m==0) = 0;

v =
     3     6     0     5
Amro
  • 123,847
  • 25
  • 243
  • 454
  • you cab probably write a better vectorized solution using a combination of CUMSUM and DIFF.. Let's see if I can figure one out :) – Amro Oct 11 '10 at 22:18
  • 1
    @Jack Lu: If you find a solution useful, please consider upvoting/accepting it. – Jonas Oct 11 '10 at 22:32
  • What does the '~= mean? Transpose of x and then check every point where cell not equal to zero? – hhh Jun 05 '13 at 10:28
  • @hhh: [`~=`](http://www.mathworks.com/help/matlab/ref/ne.html) is the element-wise inequality operator. The transpose is just a detail here, we could have explicitly specified the dimension along which to work: `[m,v] = max(cumsum(x~=0,2),[],2)`. The next line handles the case where a row was all zeros – Amro Jun 06 '13 at 07:24
2

One-line solution with bsxfun:

result = max(bsxfun(@times, x~=0, 1:size(x,2)).');

Or use the two outputs of max:

[val, result] = max(fliplr(x~=0).',[],1); %'
result = (size(A,2)+1-result).*val;
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
1

My answer's a bit twisted but it should work too

x = [ 0 9 7 0 0 0; 5 0 0 6 0 3; 0 0 0 0 0 0; 8 0 4 2 1 0 ];
[~,pos] = max([fliplr(x~=0),ones(size(x,1))],[],2);
v = size(x,2)-pos' +1;
Adrien
  • 1,455
  • 9
  • 12