For your example input, you can match character vectors as well as numbers by replacing ismember
in the linked solution with isequal
. You can get the depth at which the search value was found by tracking how many times the function has to go round the while
loop.
function [isPresent, depth] = is_in_cell(cellArray, value)
depth = 1;
f = @(c) isequal(value, c);
cellIndex = cellfun(@iscell, cellArray);
isPresent = any(cellfun(f, cellArray(~cellIndex)));
while ~isPresent
depth = depth + 1;
cellArray = [cellArray{cellIndex}];
cellIndex = cellfun(@iscell, cellArray);
isPresent = any(cellfun(f, cellArray(~cellIndex)));
if ~any(cellIndex)
break
end
end
end
Using isequal
works because f
is only called for elements of cellArray
that are not themselves cell arrays. Use isequaln
if you want to be able to search for NaN
values.
Note this now won't search inside numeric, logical or string arrays:
>> A = {1 {2; 3};4 {5 'text' 7;8 9 [10 11 12]}};
>> is_in_cell(A, 10)
ans =
logical
0
If you want that, you can define f
as
f = @(c) isequal(value, c) || isequal(class(value), class(c)) && ismember(value, c);
which avoids calling ismember
with incompatible data types, because of the 'short-circuiting' behaviour of ||
and &&
. This last solution is still a bit inconsistent in how it matches strings with character vectors, just in case that's important to you - see if you can figure out how to fix that.