Subract specific areas from array

1 view (last 30 days)
Hugo
Hugo on 6 Jan 2014
Commented: Hugo on 7 Jan 2014
I would like to find and define specific areas in an array. For example for the next array;
Array = [0 0 0 0 2 2 1 1 1 2 2 2 2 2 2 2 2 1 1 1 2 2 0 2 2 0 0 0]
i would like to define the area's with connected 2's and divide them in two groups (the area of 2's which which is limited by two 1's, and the 2's which aren't closed by two ones, but for example two zeros or a one and a zero).
In the end i would like to keep the area which is closed in by two ones and dump the rest of my array
What would be the best way to do this?
  2 Comments
Jos (10584)
Jos (10584) on 6 Jan 2014
Edited: Jos (10584) on 6 Jan 2014
What do you mean by "divide in two groups" and "dump the rest"?
It would help if you'd also given an example of the expected outcome, like:
ArrayIn = [0 0 0 0 2 2 1 1 1 2 2 2 2 2 2 2 2 1 1 1 2 2 0 2 2 0 0 0]
ArrayOut = [0 0 0 0 0 0 1 1 1 2 2 2 2 2 2 2 2 1 1 1 0 0 0 0 0 0 0 0] %?
Hugo
Hugo on 6 Jan 2014
Hi Jos,
The outcome i want is something like that, but i would like to create two arrays, so something like this:
ArrayIn = [0 0 0 0 2 2 1 1 1 2 2 2 2 2 2 2 2 1 1 1 2 2 0 2 2 0 0 0];
ArrayOut1 = [0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0];
ArrayOut2 = [0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 2 2 0 0 0]; %
So i want to have one array with the 2's which are locked in between two 1's and i want one array with al 2's which do not meet this condition.

Sign in to comment.

Accepted Answer

Azzi Abdelmalek
Azzi Abdelmalek on 6 Jan 2014
Edited: Azzi Abdelmalek on 7 Jan 2014
A= [1 2 2 1 1 1 2 2 2 2 2 1 1 2 2 0 2 2 0 0 0 1 2 2 2 1 0 1 ];
ArrayOut1=zeros(size(A));
ArrayOut2=ArrayOut1;
idx1=union(strfind(A,[1 2]),strfind(A,[0 2]));
idx2=union(strfind(A,[2 1]),strfind(A,[2 0]))+1;
v=all(A([idx1' idx2']),2);
ArrayOut1(cell2mat(arrayfun(@(x) idx1(x)+1:idx2(x)-1,find(v)','un',0)))=2;
ArrayOut2(cell2mat(arrayfun(@(x) idx1(x)+1:idx2(x)-1,find(~v)','un',0)))=2;
Or in case A start (or/and) ends with 2
A= [2 2 1 1 1 2 2 2 2 2 1 1 2 2 0 2 2 0 0 0 1 2 2 2 1 0 1 2 ];
ArrayOut1=zeros(size(A));
ArrayOut2=ArrayOut1;
A=[0 A 0];
idx1=union(strfind(A,[1 2]),strfind(A,[0 2]));
idx2=union(strfind(A,[2 1]),strfind(A,[2 0]))+1;
v=all(A([idx1' idx2']),2);
ArrayOut1(cell2mat(arrayfun(@(x) idx1(x):idx2(x)-2,find(v)','un',0)))=2
ArrayOut2(cell2mat(arrayfun(@(x) idx1(x):idx2(x)-2,find(~v)','un',0)))=2
  1 Comment
Hugo
Hugo on 7 Jan 2014
Thanks a lot, this was exactly the thing i searched for!

Sign in to comment.

More Answers (3)

Walter Roberson
Walter Roberson on 6 Jan 2014
nonz = [0 (ArrayIn ~= 0) 0];
begin_groups = strfind(nonz, [0 1]);
end_groups = strfind(nonz, [1 0]);
Now look at the locations indicated by begin_groups and see if [2 2] starts there; likewise look in the corresponding end_groups and see if it ends with [2 2]

Azzi Abdelmalek
Azzi Abdelmalek on 6 Jan 2014
ArrayIn= [0 0 0 0 2 2 1 1 1 2 2 2 2 2 2 2 2 1 1 1 2 2 0 2 2 0 0 0 ]
B=num2str(ArrayIn);
B=strrep(B,' ','');
[ii1,ii2]=regexp(B,'(?<=1)2+(?=1)','start','end');
[jj1,jj2]=regexp(B,'(?<=0)2+(?=0)|(?<=0)2+(?=1)|(?<=1)2+(?=0) ','start','end');
ArrayOut1=zeros(size(ArrayIn));
ArrayOut2=ArrayOut1;
ArrayOut1(cell2mat(arrayfun(@(x,y) x:y,ii1,ii2,'un',0)))=2
ArrayOut2(cell2mat(arrayfun(@(x,y) x:y,jj1,jj2,'un',0)))=2

Andrei Bobrov
Andrei Bobrov on 6 Jan 2014
Edited: Andrei Bobrov on 6 Jan 2014
[a,b] = regexp(num2str(A(:))','(?<=1)2*(?=1)');
t = false(size(A));
for jj = 1:numel(a)
t(a(jj):b(jj)) = true;
end
out = A.*(A==2);
out1=out.*t;
out2 = out.*~t;
or without num2str and regexp
t = [true;diff(A(:))~=0];
n = A(t);
ii = find(t);
m = bsxfun(@plus,strfind(n(:)',[1 2 1]),(1:2)');
tt = false(size(A));
for jj = 1:size(m,2), tt(ii(m(1,jj)):ii(m(2,jj))-1) = true; end
out = A.*(A==2);
out1 = out.*tt;
out2 = out.*~tt;

Community Treasure Hunt

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

Start Hunting!