EyesOfÖzil
EyesOfÖzil

Reputation: 309

How to find a non-zero number between two zeros in a cell array in matlab

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

Answers (3)

EBH
EBH

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

Tasos Papastylianou
Tasos Papastylianou

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

beaker
beaker

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

Related Questions