To resolve issues starting MATLAB on Mac OS X 10.10 (Yosemite) visit: http://www.mathworks.com/matlabcentral/answers/159016
i have a matrix like this: [1 0 0 1 1 1 1 0 1 1 0]
i need to change to: [1 0 0 4 4 4 4 0 2 2 0]
how to make a loop?thanks
No products are associated with this question.
Improve my previous code speed three times
x=[1 0 0 1 1 1 1 0 1 1 0] a=find(x); b=[ 1 diff(a)]; b(b==1)=0; b(b~=0)=1; idx=zeros(numel(a),2); e=1; c=0; d=; for k=1:numel(a) e=e+b(k); c=c*not(b(k))+1; d(c)=a(k); idx(e,:)=[d(1) c]; end for k=1:e x(idx(k,1):idx(k,1)+idx(k,2)-1)=idx(k,2); end
And finally an improved loop method which is about twice as fast as the vectorized method:
function a = RunLength_IgnoZero_loop2(a) len = length(a); c = a(1); ini = 1; b = zeros(size(a)); for ii = 2:len if a(ii) ~= c if c == 0 ini = ii; else b(ini) = ii - ini; b(ii) = ini - ii; end c = a(ii); end end
if c ~= 0 b(ini) = len - ini + 1; end a = cumsum(b);
Let x be the original row vector of 1's and 0's.
n = length(x); d = diff([0,x,0]); f1 = find(d(1:n)>0); f2 = find(d(2:n+1)<0)+1; y = zeros(1,n+1); y([f1,f2]) = [f2-f1,f1-f2]; y = cumsum(y(1:n));
clear x=[1 0 0 1 1 1 1 0 1 1 0] e=0,c=0,d= for k=1:numel(x) if x(k) e=e+not(c) c=c+1 d=[d k] idx(e,:)=[d(1) c] else c=0 d= end end for k=1:size(idx,1) x(idx(k,1):idx(k,1)+idx(k,2)-1)=idx(k,2) end
Very simple. No loop needed. You just reassign it:
m = [1 0 0 1 1 1 1 0 1 1 0] % Now make it into what you want: m = [1 0 0 4 4 4 4 0 2 2 0]
If you have some other algorithm then let's hear it. For example, leave the first element alone but take the next contiguous stretch of 1's and multiply them by 4, and take the next stretch and multiply them by 2. I couldn't figure out what algorithm you were applying, and you didn't say, and didn't say how general you needed this to be (for example can m have values other than 0 and 1, or can it be other lengths, or can it be 2D or 3D?).
An inplace method, which changes the input vector on the fly without storing an index list - this muight be an advantage for large data sets:
function a = RunLength_IgnoZero_loop1(a)
len = length(a); c = a(1); ini = 1; for ii = 2:len if a(ii) ~= c if c == 0 ini = ii; else a(ini:ii-1) = ii - ini; end c = a(ii); end end
% care about last segement: if c ~= 0 a(ini:len) = len - ini + 1; end
For the test data x = double(rand(1, 1e6) > 0.8) this vectorized method is 9 times faster than my loop approach:
function a = RunLength_IgnoZero_Vec(a)
pos = [false, a > 0, false]; start = strfind(pos, [false, true]); stop = strfind(pos, [true, false]) -1; run = stop - start + 1;
b = zeros(size(a)); b(start) = run; b(stop+1) = -run; if length(b) == length(a) a = cumsum(b); else a = cumsum(b(1:length(b) - 1)); end