Abdullah Al Mubarok
Abdullah Al Mubarok

Reputation: 91

Search particular matrix in cell array

So, I have this cell array contains n x 2 matrix in each cell. Here is the sample data :

[16 17;17 17]
<6x2 double>
<52x2 double>
[17 17;17 18]
[17 18;17 17]

What I am going to do is eliminate the duplicated matrix (matrices with same values or reversed values). in this case is [17 18; 17 17] (5th row), because we already have [17 17; 17 18] (4th row)

I tried using unique function but it says that the function just worked for strings. I also tried to find it with cellfun like this

cellfun(@(x) x==whatToSearch, lineTraced, 'UniformOutput', false)

but it says 'Matrix dimension must agree'

Thanks in advance.

Upvotes: 1

Views: 72

Answers (2)

eigenchris
eigenchris

Reputation: 5821

Here is a solution. Given a m x 1 column cell array C of matrices, this code deletes the equivalent duplicates. (Here it will delete the 4th and 5th matrices, which are equivalent to the 1st).

C{1} = magic(3);
C{2} = magic(4);
C{3} = magic(5);
C{4} = C{1};
C{5} = flipud(C{1});

myEq = @(A,B) isequal(A,B) | isequal(A,flipud(B)); %// equivalence operator tests for same or up-down flipped matrix
C = C(:);                                          %// ensure the cell array is a column
Crep = repmat(C,1,size(C,1));                      %// repeat cell array along rows to get a square
comp = cellfun(myEq,Crep,Crep');                   %'//get a comparison matrix by comparing with transpose
comp = tril(comp) - eye(size(comp));               %// ignore upper triangle and diagonal
idx = find( sum(comp,2)==0 );                      %// get index of matrices we want to keep
result = C(idx);                                   %// get result

The output is deletes the 4th and 5th matrices, leaving the first three magic matrices:

>> result

result = 

[3x3 double]    [4x4 double]    [5x5 double]

>> result{1}, result{2}, result{3}

ans =

     8     1     6
     3     5     7
     4     9     2


ans =

    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1


ans =

    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9

Upvotes: 1

Sevenless
Sevenless

Reputation: 2835

Here's code that does what you want.

mydup = rand(5,2);
mycell = {mydup;mydup;rand(7,2);rand(3,2);rand(5,2)}

myNewCell = trimCell(mycell)

Where trimCell is the function below:

function myNewCell = trimCell(myCell)


exclude = false(size(myCell));
for iter = 1:size(myCell,1)
    toCompare = myCell{iter};
    comparisons = cellfun(@(x) all(size(x)==size(toCompare)) && myEquals(x, toCompare),myCell);
    % comparisons has at least 1 true in it, because toCompare==toCompare
    exclude(iter) = sum(comparisons)>1;
end

myNewCell = myCell(~exclude);

end

function boolValue = myEquals(x,y)

assert(all(size(x)==size(y)));

boolValue = true;
for iter = 1:size(x,1)
    thisRow = all(sort(x(iter,:))==sort(y(iter,:)));
    boolValue = boolValue && thisRow;
    if ~boolValue
       return 
    end

end

end

Basically, what this function does, is, for each matrix in the cell it checks first if the sizes are equal. If the sizes aren't equal, then we know the matrices aren't equal, even if we reorder the rows.

If they are the same size, then we need to check if they're equal after row reordering. That's accomplished by the function myEquals which goes through row by row and sorts the rows before comparing them. It exits with false on the first row it finds that is not equal after reordering.

Hope this helps, Andrew

Upvotes: 1

Related Questions