2

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
Robert Seifert
  • 25,078
  • 11
  • 68
  • 113
JustCurious
  • 1,848
  • 3
  • 30
  • 57
  • 3
    Do you need it or are you JustCurious? (sorry I couldnt hold it) Anyway, have a look at this question, something may help you: http://stackoverflow.com/questions/25851305/fastest-way-of-finding-repeated-values-in-different-cell-arrays-of-different-siz – Ander Biguri Feb 27 '15 at 12:57
  • Does it have to be the first element in **all** of `my_cells{1}{1}`, `my_cells{1}{2}`, `my_cells{1}{3}`... `my_cells{1}{6}` to declare that the first index of `my_cells` is a match or **any** one of them? – Divakar Feb 27 '15 at 13:03
  • the first column is let's say the `user_id`. So i am looking to find ids that matches specific scalar or vector. e.g 977. – JustCurious Feb 27 '15 at 13:16
  • three indices. my_cells{i}{j} (k,:). where (i ,j) are the indexes of the cells containing that number and k the row containing it, if `my_cells{i}{j}` is a matrix. – JustCurious Feb 27 '15 at 13:29
  • 1
    I am JustCurious, could you add the output for the given data with the edits? Like "My expected output must be ..blah blah.. and few more blahs"? – Divakar Feb 27 '15 at 13:45
  • `my_cells{1}{5}=[949.0000 7.0000 0.9241 474.0000 4.0000 0.9926]` is there a semicolon missing? Also be more clear on the output. – Robert Seifert Feb 27 '15 at 17:02
  • if you copy and paste it in matlab, you do not have to add the semi colon. – JustCurious Mar 01 '15 at 11:50

1 Answers1

3

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.

Robert Seifert
  • 25,078
  • 11
  • 68
  • 113
  • the case you describe is not common but it is possible for lower ids. If instead of looking for 977 I was for 1 or 7. So, I have to consider this – JustCurious Feb 27 '15 at 13:26
  • @JustCurisos I don't understand this comment, can you explain what is not working if `a = 1` or `a = 7`? – Robert Seifert Feb 27 '15 at 13:28
  • I maybe misunderstood the second part of your answer. Why 977 is in the second column? What is your point? I have added more examples for `my_cells`. my_cells{i}{j} might be a matrix. So, i want three things. All the "i" and "j" indices that contain the id or ids that i am looking for as well as the row in the matrix they are in. So for the example above would be i=[1 2], j=[1 1] k=[1 1] or something like that. – JustCurious Feb 27 '15 at 13:33
  • I have updated the examples. I tried your suggestion but I get errors. Error using cat Dimensions of matrices being concatenated are not consistent. – JustCurious Feb 27 '15 at 13:42
  • 1
    @JustCurios To avoid missunderstandings please edit the provided input in your question so we can just copy&paste it. Also add the desired output for this input. Otherwise it's really hard to get everything right in the first place and dozens of corrections are always pain in the ass for answerers ;) – Robert Seifert Feb 27 '15 at 15:10
  • I changed the input a bit. so that you can copy/paste it. Also, i updated what i expect as an output. it might not be exactly like this but the idea is to find those indices so as to make changes in the other columns of the entries that have 977 as an id. – JustCurious Feb 27 '15 at 15:25
  • @Divakar This qualifies for the mentalist category. – rayryeng Feb 27 '15 at 15:25