Asked by Simone Loreti
on 16 Sep 2019 at 13:00

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 Matt J
on 16 Sep 2019 at 13:07

Accepted Answer

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

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

Answer by Bruno Luong
on 16 Sep 2019 at 13:23

Edited by Bruno Luong
on 16 Sep 2019 at 15:46

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 at 13:35

Edited by the cyclist
on 16 Sep 2019 at 13:38

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 Simone Loreti
on 16 Sep 2019 at 14:14

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

Simone Loreti
on 16 Sep 2019 at 15:36

Bruno Luong
on 16 Sep 2019 at 15:52

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 {...})

Simone Loreti
on 16 Sep 2019 at 19:08

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.