Search code examples
matlabmultidimensional-arraynested-loopscell-array

MATLAB: Using cellfun with multi level cell array


I have a multi-level cell array. The individual levels could be of different size. I am wondering how I can apply cellfunto the lowest level. Imagine the following mulit-level cell array:

a = {randi(10,5,1), randi(5,5,1)}
b = randi(100,5,1,10)
f = {a,b}

Now, I would like to drill down as much as possible and apply cellfun to the deepest level possible of f. At the and of each level, there is a 2D/3D matrix. Let's say, I simply want to add 5 to each value. What's the most efficient way?

Here's the result I am looking for.

[a_nRows, a_nCols, a_nPages] = size(a)
x = cellfun(@plus, f{1}, repmat({5}, a_nRows, a_nCols, a_nPages), 'UniformOutput', false)
y = cellfun(@plus, f(2), {5}, 'UniformOutput', false)

Solution

  • You can use recursion for this.

    Firstly, define a function which does one of two things

    1. If the input is a numeric matrix, apply some operation.
    2. If the input is a cell, call this same function with the cell's contents as inputs.

    The function would look something like this (defined locally to another function or in its own m file):

    function out = myfunc( in, op )
        if iscell( in )
            out = cellfun( @(x) myfunc(x, op), in, 'UniformOutput', false );
        elseif isnumeric( in )
            out = op( in );
        else
            error( 'Cell contents must be numeric or cell!' )
        end
    end
    

    Then you can call myfunc on your cell. Here is an example similar to yours:

    a = {[1 2; 3 4], {eye(2), 10}}; % Nested cell arrays with numeric contents
    op = @(M) M + 5;                % Some operation to apply to all numeric contents
    
    myfunc( a, op )
    % >> ans = 
    %     { [6 7; 8 9], {[6 5; 5 6], 15}}
    

    Directly using your example, the output of myfunc(f, @(M)M+5) is the same as your {x, y{1}} - i.e. the operation op is applied to every cell and nested cell with the result structured the same as the input.