Asked by Daniel Boateng
on 12 Apr 2019

I have an array like this [2 2 3 4 0 0 0 0 7 8 2 2]. Please i want to add the numbers excluding the zeros to have something like this[11 0 0 0 0 19] Please is there a way I can do it. Thanks

Answer by Jonathan
on 12 Apr 2019

Accepted Answer

The following code should do what you want. There may be some way to do this more elegantly, but I think this works and should be fairly efficient. I haven't thoroughly tested it for all edge cases. If this works for you it would be good to make it into a function that just took the input vector and returned the condensed output.

% code to condense non-zero elements in a vector into single values

% for example x = [0 1 0 2 2 3 4 0 0 0 0 7 8 2 2 0 3 0] should give

% xCond = [0 1 0 11 0 0 0 0 19 0 3 0]

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

% pad start and end of original vector with zero to allow detection of

% transitions to at ends of vector

xPad = [0 x 0];

% find locations where we transition from zero to non-zero elements

startIdx = find(xPad(1:end-1) == 0 & xPad(2:end)~=0);

% find locations where we transition from non-zero to zero elements

stopIdx = find(xPad(2:end)==0 & xPad(1:end-1)~=0)-1;

% find the number of non-zero segments (each pair of start and stop idx

% defines a non-zero segment that must be condensed into a single value

numSegments = length(startIdx); % startIdx and stopIdx are same length

% find the number of zero values

numZeros = sum(x == 0);

% Each pair of start and stop idx defines a non-zero segment that must be

% condensed into a single value. The length of the condensed vector will be

% the number of non-zero segments plus the number of zero elements that are

% left as spacers

% preallocate an appropriately sized vector to hold the condensed vector

xCond = zeros(1,numSegments + numZeros);

% loop through segments computing condensed sums and forming condensed

% vector

idx = startIdx(1); % initial location in the output vector

for k = 1:numSegments

% condense current segment

xCond(idx) = sum(x(startIdx(k):stopIdx(k)));

% increment the count to the next location

if k + 1 <= numSegments % watch for end condition

idx = idx + (startIdx(k+1) - stopIdx(k));

end

end

Daniel Boateng
on 12 Apr 2019

Thank you very much. That is what I expected

Sign in to comment.

Answer by Stephen Cobeldick
on 12 Apr 2019

>> x = [0,0,0,1,0,2,2,3,4,0,0,0,0,7,8,2,2,0,3,0];

>> y = cumsum(x==0 | [true,x(1:end-1)==0]);

>> z = accumarray(y(:),x(:))

z =

0

0

0

1

0

11

0

0

0

0

19

0

3

0

Jonathan
on 13 Apr 2019

madhan ravi
on 13 Apr 2019

Daniel Boateng
on 14 Apr 2019

this one also short and good. Thanks for your effort

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.