JustCurious
JustCurious

Reputation: 1858

How to find elements in a 2D cell array more efficiently?

I have a 2D cell array as follows:

my_cells=
Columns 1 through 11

{1x6 cell}    {1x8 cell}    {1x2 cell}    {1x7 cell}    {1x7 cell}    {1x6 cell}    {1x7 cell}    {1x7 cell}    {1x8 cell}    {1x5 cell}    {1x7 cell}

 Columns 12 through 22

{1x4 cell}    {1x3 cell}    {1x3 cell}    {1x5 cell}    {1x5 cell}    {1x4 cell}    {1x3 cell}    {1x5 cell}    {1x4 cell}    {1x5 cell}    {1x4 cell}

 Columns 23 through 24

{1x6 cell}    {1x1 cell}

Each one of these cells has a number of arrays as follows:

my_cells{1}= [1x3 double]    [1x3 double]    [1x3 double]    [1x3 double]    [2x3 double]    [1x3 double]

and

my_cells{1}{1}= [977.0000    1.0000    0.9231]
my_cells{1}{2}= [286.0000    7.0000    0.9789]
my_cells{2}{1}= [977.0000    1.0000    0.9231]
my_cells{3}{1}= [286.0000    7.0000    0.9789]
my_cells{1}{5}=[949.0000    7.0000    0.9241
                474.0000    4.0000    0.9926]

I would like to find, for example, where else the number 977 might appear as a first element in my_cells. However, I would like to avoid nested for loops to increase the performance if it is possible. Is there an easy and fast way to do it? So the output would be something like 1,1,1 and 2,1,1.

An example that is not efficient looks like:

    number=977;
    for i=1:N
        M=size(my_cells{i},2);
        for j=1:M
            [a,ind]=ismember(number,my_cells{i}{j}(:,1));
            if sum(a)~=0
                ind( ~any(ind,2), : ) = [];
                my_cells{i}{j}(ind,2)=my_cells{i}{j}(ind,2)-1;
            end
        end
    end

Upvotes: 2

Views: 254

Answers (1)

Robert Seifert
Robert Seifert

Reputation: 25232

This should do it:

%// Value to check
a = 977;

%// indices of cells containing a at the first place
idx = cellfun(@(x) find(x == a,1) == 1, my_cells)

%// first cell containing a
cellsWith977atFirst = my_cells(idx)

For

my_cells = { [977 1 2] [2 977 977] [977 2 1] }

it will return

celldisp(cellsWith977atFirst)

cellsWith977atFirst{1} =   977     1     2
cellsWith977atFirst{2} =   977     2     1

But I just have seen that your input is actually:

my_cells = { {[977 1 2]} {[2 977 977]} {[977 2 1]} }

you should rethink, if this way of storing your data actually makes sense. You need to change the code for this case to:

idx = cellfun(@(x) find(cell2mat(x) == a,1) == 1, my_cells)

you noe could access my_cells again by

cellsWith977atFirst = my_cells(idx);

but you may prefer this

cellsWith977atFirst = cellfun(@cell2mat, my_cells(idx), 'uni',0)

Maybe you need to vary the code a little depending on how exactly you wish your output.

Upvotes: 3

Related Questions