Sort values of a vector in an array according to gaps

2 views (last 30 days)
Hi. I have a vector that looks something like this:
A = [1; 2; 3; 4; 6; 7; 8; 9; 10; 12; 13; 14; 15; 16; 17; 19; 20];%and so on
and another vector containing the gaps in A:
B = [5; 11; 18]
In this example, the values 5, 11 and 18 are missing. The vector I am working with is a lot longer and has the values missing in random places.
What I want to do is create an array out of A that starts a new column every time there's a gap:
CELL = {[1; 2; 3; 4], [6; 7; 8; 9; 10], [12; 13; 14; 15; 16; 17], [19; 20]};
I wrote a loop that does just that, but because A is so long, my computer eventually freezes. Any suggestions for a faster method using logical operations or something (I'm not so good with those, yet).
Thanks in advance!

Accepted Answer

Azzi Abdelmalek
Azzi Abdelmalek on 13 Dec 2013
A = [1; 2; 3; 4; 6; 7; 8; 9; 10; 12; 13; 14; 15; 16; 17; 19; 20]
idx=diff(A);
ii2=unique([find(idx>1) ;numel(A)]);
ii1=[1 ;ii2(1:end-1)+1];
out=arrayfun(@(x,y) A(x:y),ii1,ii2,'un',0);
celldisp(out)

More Answers (2)

Image Analyst
Image Analyst on 13 Dec 2013
How many elements are in B? A for loop shouldn't take that long if it's under ten million or so. The time is probably taken up in creating the cell array's cells rather than the for loop iteration itself. I can do a for loop of 10 million iterations in 0.03 seconds, so the for loop itself is fast. It's creating the cells that takes time.
Possible solution to speed it up: Can you take diff(B) to find out how long the longest stretch will be and then preallocate a normal int32 rectangular array to hold the output? I know that you'll have a ragged right edge but you can just flag those with some special number like -999 or something so you know they're not to be used.
  1 Comment
Marc Jakobi
Marc Jakobi on 13 Dec 2013
Thanks for your answer! I ended up finding an entirely different solution to my problem (the initial problem was to fill gaps in a third vector that were indexed by vector A with the value indexed by B). So I won't be needing the array CELL any more.

Sign in to comment.


Andrei Bobrov
Andrei Bobrov on 13 Dec 2013
Edited: Andrei Bobrov on 13 Dec 2013
A = [1; 2; 3; 4; 6; 7; 8; 9; 10; 12; 13; 14; 15; 16; 17; 19; 20];
B = [5; 11; 18];
i0=zeros(numel([A(:);B(:)]),1);
i0(B)=1;
i1=cumsum(i0)+1;
CELL1 = accumarray(i1(A),A,[],@(x){x});
or in one line:
CELL1 = accumarray(cumsum([true;diff(A)>1]),A,[],@(x){x});

Community Treasure Hunt

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

Start Hunting!