Search code examples
matlabcell-arraymatrix-indexing

matlab: find and replace elements of matrices within a cell array


I have a cell array that contains multiple matrices of different size. I'd like to find & replace all elements of the matrices by a condition, e.g. replace all 1's with 0's. I found a temporary solution from find and replace values in cell array, but it seems way more complicated that it should be:

Example:

A = {[1 2;3 4] [1 2 3;4 5 6;7 8 9]}
replacement = 1:9;
replacement(replacement==1)=0;
A = cellfun(@(x) replacement(x) ,A,'UniformOutput',false)
A{:}

ans =

 0     2
 3     4

ans =

 0     2     3
 4     5     6
 7     8     9

So it works but I feel like this should be doable without first specifying a list of replacement values and then "exchanging" all elements. (I have to do this a lot and with more complex conditions). Any suggestions?


Solution

  • One approach would be with elementwise-multiplication with the mask of such 1s -

    cellfun(@(x) (x~=1).*x, A, 'uni',0)
    

    Sample run -

    >> celldisp(A)  % Input cell array
    A{1} =
         3     2
         1     4
    A{2} =
         7     1     3
         4     5     1
         7     8     9
    >> C = cellfun(@(x) (x~=1).*x, A, 'uni',0);
    >> celldisp(C)
    C{1} =
         3     2
         0     4
    C{2} =
         7     0     3
         4     5     0
         7     8     9
    

    Generic case : To make it generic that could replace any number by any other number, we need a slight modification, like so -

    function out = replace_cell_array(A, oldnum, newnum)
    
    out = cellfun(@(x) x+(x==oldnum).*(newnum-oldnum), A, 'uni',0);
    

    Sample runs -

    >> A = {[1 2;3 5] [1 2 3;5 5 3;7 8 9]}; % Input cell array
    >> celldisp(A)
    A{1} =
         1     2
         3     5
    A{2} =
         1     2     3
         5     5     3
         7     8     9
    >> celldisp(replace_cell_array(A,1,0)) % replace 1s with 0s
    ans{1} =
         0     2
         3     5
    ans{2} =
         0     2     3
         5     5     3
         7     8     9
    >> celldisp(replace_cell_array(A,3,4)) % replace 3s with 4s
    ans{1} =
         1     2
         4     5
    ans{2} =
         1     2     4
         5     5     4
         7     8     9