How to cumulatively add consecutive ones between zeros in a logical vector

3 ビュー (過去 30 日間)
Shawn
Shawn 2017 年 10 月 26 日
コメント済み: Shawn 2017 年 10 月 27 日
I have a vector that looks like
x = [0 0 1 1 0 0 1 1 1 0 0 1]
and am trying to obtain
y = [0 0 1 2 0 0 1 2 3 0 0 1]
without using a loop. Any help would be much appreciated. The answer by Roger Stafford in https://www.mathworks.com/matlabcentral/answers/118828-how-to-count-the-number-of-consecutive-numbers-of-the-same-value-in-an-array is along the lines of what I am trying to achieve, but I am currently unable to manipulate his code to serve my purpose.

採用された回答

Andrei Bobrov
Andrei Bobrov 2017 年 10 月 26 日
y = x(:)';
ii = accumarray(bwlabel(y(:))+1,1);
y = [y,0];
y(strfind(y,[1 0])+1) = -ii(2:end);
out = cumsum(y(1:end-1));
  4 件のコメント
Shawn
Shawn 2017 年 10 月 26 日
Thank you very much! This is excellent.
Shawn
Shawn 2017 年 10 月 27 日
I added comments to the code in case anyone else is trying to understand it since it took me quite some time to understand the logic.
%%Cumulatively Add Consecutive Ones Between Zeros in a Logical Vector
x = [1 1 0 0 0 0 0 1 1 1 1 0 1 1 0 1 1 0 1 1 1 0 1 0 1 0 1 0 0 1 1 1];
%diff([0;x(:)]) vertically concatenates, adds a leading 0, and then
%takes the difference between consecutive points
%cumsum(diff([0;x(:)]) == 1) finds the location of each change from 0 to 1,
%keeps that value constant elementwise until another 0 to 1 shows up, and
%then increments by 1 each time it shows up
%cumsum(diff([0;x(:)]) == 1).*x(:) elementwise multiplies the previous
%equation by the original vector, which will set corresponding 0 elements
%to 0
%accumarray(cumsum(diff([0;x(:)]) == 1).*x(:)+1,1) adds one to the previous
%equation and then creates histogram style binning of the appearance of
%each number from 1 on (since 1 was added, the index corresponds to one
%more than the actual number)
ii = accumarray(cumsum(diff([0;x(:)]) == 1).*x(:)+1,1);
%adds a trailing 0 to the original vector
y = [x,0];
%strfind(y,[1 0])+1 finds the locations of every instance of a 1 then a 0
%showing up and then adds 1 to get the indeces of that 0
%y(strfind(y,[1 0])+1) = -ii(2:end) replaces the previously described 0
%indeces with the negative of the corresponding bin number of how many
%times in a row the number 1 was repeated prior to it (recall that the
%index is one greater than the actual number and that we counted up from 1
%every time that a 0 to 1 showed up)
y(strfind(y,[1 0])+1) = -ii(2:end);
%now we cumulatively add each number together, so whenever we have ones
%they will add and then thanks to the last step, the 0 following a 1
%contains the negative of the number of ones that preceeded it, so it will
%reset the count to 0
out = cumsum(y(1:end-1));

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeLogical についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by