Reputation: 309
I have a cell array (11000x500)
with three different type of elements.
1) Non-zero doubles
2) zero
3) Empty cell
I would like to find all occurances of a non-zero number between two zeros.
E.g. A = {123 13232 132 0 56 0 12 0 0 [] [] []};
I need the following output
out = logical([0 0 0 0 1 0 1 0 0 0 0 0]);
I used cellfun
and isequal
like this
out = cellfun(@(c)(~isequal(c,0)), A);
and got the follwoing output
out = logical([1 1 1 0 1 0 1 0 0 1 1 1]);
I need help to perform the next step where i can ignore the consecutive 1's
and only take the '1's' between two 0's
Could someone please help me with this?
Thanks!
Upvotes: 4
Views: 181
Reputation: 10440
Here is a quick way to do it (and other manipulations binary data) using your out
:
out = logical([1 1 1 0 1 0 1 0 0 1 1 1]);
d = diff([out(1) out]); % find all switches between 1 to 0 or 0 to 1
len = 1:length(out); % make a list of all indices in 'out'
idx = [len(d~=0)-1 length(out)]; % the index of the end each group
counts = [idx(1) diff(idx)]; % the number of elements in the group
elements = out(idx); % the type of element (0 or 1)
singles = idx(counts==1 & elements==1)
and you will get:
singles =
5 7
from here you can continue and create the output as you need it:
out = false(size(out)); % create an output vector
out(singles) = true % fill with '1' by singles
and you get:
out =
0 0 0 0 1 0 1 0 0 0 0 0
Upvotes: 3
Reputation: 22215
Another solution, this completely avoids your initial logical matrix though, I don't think you need it.
A = {123 13232 132 0 56 0 12 0 0 [] [] []};
N = length(A);
B = A; % helper array
for I = 1 : N
if isempty (B{I}), B{I} = nan; end; % convert empty cells to nans
end
B = [nan, B{:}, nan]; % pad, and collect into array
C = zeros (1, N); % preallocate your answer array
for I = 1 : N;
if ~any (isnan (B(I:I+2))) && isequal (logical (B(I:I+2)), logical ([0,1,0]))
C(I) = 1;
end
end
C = logical(C)
C =
0 0 0 0 1 0 1 0 0 0 0 0
Upvotes: 1
Reputation: 16791
You can use conv
to find the elements with 0 neighbors (notice that the ~
has been removed from isequal
):
out = cellfun(@(c)(isequal(c,0)), A); % find 0 elements
out = double(out); % cast to double for conv
% elements that have more than one 0 neighbor
between0 = conv(out, [1 -1 1], 'same') > 1;
between0 =
0 0 0 0 1 0 1 0 0 0 0 0
(Convolution kernel corrected to fix bug found by @TasosPapastylianou where 3 consecutive zeros would result in True.)
That's if you want a logical vector. If you want the indices, just add find
:
between0 = find(conv(out, [1 -1 1], 'same') > 1);
between0 =
5 7
Upvotes: 2