Asked by Sim
on 16 Sep 2019

I have a 1×2 nested cell array A (cell array within a cell array):

A =

1×2 cell array

{43612×7 cell} {863892×7 cell}

where

A{1} =

{'Up' } {'Down' } {'Left' } {'Right'} {'BLUE'}

{'1' } {'7' } {'1' } {'8' } {'3' }

{'2' } {'7' } {'4' } {'3' } {'7' }

{'9' } {'1' } {'6' } {'2' } {'1' }

{'...' } {'...' } {'...' } {'...' } {'...' }

A{2} =

{'Up' } {'Down' } {'Left' } {'Right'} {'RED' }

{'2' } {'1' } {'1' } {'1' } {'2' }

{'6' } {'1' } {'7' } {'4' } {'2' }

{'5' } {'9' } {'8' } {'4' } {'4' }

{'...' } {'...' } {'...' } {'...' } {'...' }

If possible, by using only 1 or 2 lines of code, I would like to know if the text 'BLUE' is in A{1} or in A{2}.

The full answer would be: 'BLUE' is in A{1}(1,5), but I would like to know just the first index of A, i.e. either A{1} or A{2}.

Therefore, if we consider only the firs index of A, i.e. either A{1} or A{2}, my Result would be something like:

Result = 2x1 logical array

1

0

Which means my 'BLUE' text is in A{1}.

My first attempt started by using 'strcmp' in this way:

cellfun(@(x) strcmp(x, 'BLUE'), A, 'UniformOutput', false)

But then I got stuck... Any suggestion to get what I need in only 1 or 2 lines of code ?

Hope my question is clear enough.... Thanks a lot and best regards!

Answer by Bruno Luong
on 16 Sep 2019

Edited by Bruno Luong
on 16 Sep 2019

A{1} = { ...

{'Up' } {'Down' } {'Left' } {'Right'} {'BLUE'}

{'1' } {'7' } {'1' } {'8' } {'3' }

{'2' } {'7' } {'4' } {'3' } {'7' }

{'9' } {'1' } {'6' } {'2' } {'1' }

{'...' } {'...' } {'...' } {'...' } {'...' }}

A{2} = {...

{'Up' } {'Down' } {'Left' } {'Right'} {'RED' }

{'2' } {'1' } {'1' } {'1' } {'2' }

{'6' } {'1' } {'7' } {'4' } {'2' }

{'5' } {'9' } {'8' } {'4' } {'4' }

{'...' } {'...' } {'...' } {'...' } {'...' }}

% testfun (ONELINE function)

% EDIT version

% returns 1 x 2 boolean arrays B, B(i) is TRUE if word exists in A{i}

testfun = @(word) ismember([0 1],find(strcmp([A{1}{:} A{2}{:}], word))>numel(A{1}));

testfun('BLUE')

testfun('RED')

testfun('Up')

testfun('YELLOW')

testfun('3')

testfun('5')

Sign in to comment.

Answer by the cyclist
on 16 Sep 2019

Edited by the cyclist
on 16 Sep 2019

Here is a one-liner:

cellfun(@(y)any(any(cellfun(@(x)isequal(x,{'BLUE'}),y))),A)

I stumbled across this function for dealing with nested cell arrays. I did not try it myself, but it could make this a bit more elegant-looking.

Sign in to comment.

Answer by Sim
on 16 Sep 2019

Dear All,

Thanks a lot for your help!

I tried all the solutions proposed (so far) by Matt J, Bruno Luong and the cyclist:

clear all; clc;

A{1} = { ...

{'Up' } {'Down' } {'Left' } {'Right'} {'BLUE'}

{'1' } {'7' } {'1' } {'8' } {'3' }

{'2' } {'7' } {'4' } {'3' } {'7' }

{'9' } {'1' } {'6' } {'2' } {'1' }

{'...' } {'...' } {'...' } {'...' } {'...' }};

A{2} = {...

{'Up' } {'Down' } {'Left' } {'Right'} {'RED' }

{'2' } {'1' } {'1' } {'1' } {'2' }

{'6' } {'1' } {'7' } {'4' } {'2' }

{'5' } {'9' } {'8' } {'4' } {'4' }

{'...' } {'...' } {'...' } {'...' } {'...' }};

% Matt J

tic

B = cellfun(@(x) strcmp(x, 'BLUE'), A, 'UniformOutput', false);

cellfun(@(c) any(c(:)), B)

toc

% Bruno Luong

tic

testfun = @(word) unique((find(strcmp([A{1}{:} A{2}{:}], 'BLUE'))>numel(A{1}))+1);

testfun('BLUE')

toc

% the cyclist

tic

cellfun(@(y)any(any(cellfun(@(x)isequal(x,{'BLUE'}),y))),A)

toc

I got as follows:

% Matt J

ans =

1×2 logical array

0 0

Elapsed time is 0.002689 seconds.

% Bruno Luong

ans =

1

Elapsed time is 0.004951 seconds.

% the cyclist

ans =

1×2 logical array

1 0

Elapsed time is 0.002189 seconds.

To me - If I did everything correctly - it looks like that the best answer in terms of elapsed time is that one proposed by the cyclist. Therefore, I would like to accept his/her answer.

I greatly appreciate all your ideas and I thank you all for your efforts and time.

Regards,

SL

Sim
on 16 Sep 2019

Bruno Luong
on 16 Sep 2019

Matt edit his code and correct the BUG, now his code runs about the same time as mine.

clear

createfun = @(s) arrayfun(@(x) {sprintf('%d',x)}, ceil(1000*rand(s)), 'unif',0);

A{1}=createfun([43612 7]);

A{2}=createfun([863892 7]);

% Matt J

tic

B = cellfun(@(x) strcmp([x{:}], '123'), A, 'UniformOutput', false);

matt_r = cellfun(@(c) any(c(:)), B);

toc % Elapsed time is 4.430430 seconds.

tic

testfun = @(word) ismember([0 1],find(strcmp([A{1}{:} A{2}{:}], word))>numel(A{1}));

bruno_r = testfun('123');

toc % Elapsed time is 3.967751 seconds.

% the cyclist

tic

cyclist_r = cellfun(@(y)any(any(cellfun(@(x)isequal(x,{'123'}),y))),A);

toc % Elapsed time is 22.860207 seconds.

Edit fix createfun BUG (forget inner {...})

Sim
on 16 Sep 2019

Thanks a lot Bruno! Yes, your solutions are very similar in terms of elapsed time... I could give an ex-aequo "accept answer" to both, but I dont know how to do it...Is that possible ?

Just a curiosity: what do you get as results for "matt_r", "bruno_r" and "cyclist_r" ?

Thanks again for these interesting solutions!

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.