arrays - Split vector in MATLAB -


i'm trying elegantly split vector. example,

vec = [1 2 3 4 5 6 7 8 9 10] 

according vector of 0's , 1's of same length 1's indicate vector should split - or rather cut:

cut = [0 0 0 1 0 0 0 0 1 0] 

giving cell output similar following:

[1 2 3] [5 6 7 8] [10] 

solution code

you can use cumsum & accumarray efficient solution -

%// create id/labels use accumarray later on id = cumsum(cut)+1     %// mask valid values cut , vec corresponding ones in cut mask = cut==0          %// output accumarray using masked ids , vec values  out = accumarray(id(mask).',vec(mask).',[],@(x) {x}) 

benchmarking

here performance numbers when using large input on 3 popular approaches listed solve problem -

n = 100000;  %// input datasize  vec = randi(100,1,n); %// random inputs cut = randi(2,1,n)-1;  disp('-------------------- cumsum + accumarray') tic id = cumsum(cut)+1; mask = cut==0; out = accumarray(id(mask).',vec(mask).',[],@(x) {x}); toc  disp('-------------------- find + arrayfun') tic n = numel(vec); ind = find(cut); ind_before = [ind-1 n]; ind_before(ind_before < 1) = 1; ind_after = [1 ind+1]; ind_after(ind_after > n) = n; out = arrayfun(@(x,y) vec(x:y), ind_after, ind_before, 'uni', 0); toc  disp('-------------------- cumsum + arrayfun') tic cutsum = cumsum(cut); cutsum(cut == 1) = nan;  %don't include cut indices sumvals = unique(cutsum);      % find values use in indexing vec output sumvals(isnan(sumvals)) = [];  %remove nan values sumvals output = arrayfun(@(val) vec(cutsum == val), sumvals, 'uniformoutput', 0); toc 

runtimes

-------------------- cumsum + accumarray elapsed time 0.068102 seconds. -------------------- find + arrayfun elapsed time 0.117953 seconds. -------------------- cumsum + arrayfun elapsed time 12.560973 seconds. 

special case scenario: in cases might have runs of 1's, need modify few things listed next -

%// mask valid values cut , vec corresponding ones in cut mask = cut==0    %// setup ids differently time. idea have successive ids. id = cumsum(cut)+1 [~,~,id] = unique(id(mask))  %// output accumarray using masked ids , vec values  out = accumarray(id(:),vec(mask).',[],@(x) {x}) 

sample run such case -

>> vec vec =      1     2     3     4     5     6     7     8     9    10 >> cut cut =      1     0     0     1     1     0     0     0     1     0 >> celldisp(out) out{1} =      2      3 out{2} =      6      7      8 out{3} =     10 

Comments

Popular posts from this blog

shopping cart - Page redirect not working PHP -

php - How to modify a menu to show sub-menus -

python - Installing PyDev in eclipse is failed -