How can I replace elements in a vector if a certain condition is true?

Hi, I need some help with the following problem: I have a vector that contains negative numbers, zeros & ones. For example, one sequence could look like this
-5 0 0 0 0 1 0 1 0 0 0 -3 0 0 0 1 0 0 1 0 0 1 0 -1 0 0 0 1 0 0 1...
What I want to do is find out if there are only two '1's between one negative number and the next negative number (while the '0's are not important). If that is not the case, for instance -3 above is followed by 3 '1's before the next negative number occurs, I would like to replace this negative number (-3) & the following '1's with 0. So my result would be:
-5 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 1...
I hope that makes sense & that someone can help me!

 Accepted Answer

other variant:
A = [-5 0 0 0 0 1 0 1 0 0 0 -3 0 0 0 1 0 0 1 0 0 1 0 -1 0 0 0 1 0 0 1]
out = A(:);
As = sign(A(:));
t = find(As ~= 0);
ii = cumsum(As(t)==-1);
jj = accumarray(ii,1) > 3;
out(t(jj(ii))) = 0

More Answers (1)

Method one: indexing. This brute-force method is easy to understand and implement, but it is not very generalized (changing it is not trivial), it is a little bulky (increases possibility of making mistakes), and it requires large intermediate variables. This method could be adapted to use loops, for some versatility.
V = [-5,0,0,0,0,1,0,1,0,0,0,-3,0,0,0,1,0,0,1,0,0,1,0,-1,0,0,0,1,0,0,1];
idx = V~=0;
U = V(idx);
ido = U==1;
idn = U<0 & [ido(2:end),false(1,1)] & [ido(3:end),false(1,2)] & [ido(4:end),false(1,3)];
idr = idn | [false(1,1),idn(1:end-1)] | [false(1,2),idn(1:end-2)] | [false(1,3),idn(1:end-3)];
U(idr) = 0;
V(idx) = U;
giving an output of:
>> sprintf(' %d',V)
ans =
-5 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 1
Method two: regular expressions. Another option would be to use regexprep and a regular expression, which does require converting to char array, but are in themselves quite versatile: they can be quickly adapted or changed.
V = [-5,0,0,0,0,1,0,1,0,0,0,-3,0,0,0,1,0,0,1,0,0,1,0,-1,0,0,0,1,0,0,1];
idx = V~=0; % ignore the zeros
str = sprintf(',%d',V(idx)); % convert to string
fun = @(s)regexprep(s,'-?\d+','0');
str = regexprep(str,'-\d+(,\d+){3,}','${fun($0)}'); % search and replace pattern
V(idx) = sscanf(str,',%d'); % convert back to numeric
and the output is:
>> sprintf(' %d',V)
ans =
-5 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 1

Categories

Asked:

on 10 Jun 2017

Commented:

on 10 Jun 2017

Community Treasure Hunt

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

Start Hunting!