This is interesting. Your examples are performing two different operations, which happen to lead to the same result. It's kind of fun to explore.
TL;DR. You should generally use arrayfun
when your input is an array, and cellfun
when your input is a cell, although you can often force arrayfun
to do the job, with varyig levels of syntax hell.
Fundamentally, arrayfun
is meant to operate on arrays and cellfun
is meant to operate on cells. But, the Matlab-wise will note that a cell is nothing more than an array of "cells", so arrayfun
works anyway.
As you point out, the following two lines perform the same operation:
cellfun(@(c) c, {'one' 'two' 'three'}, 'uniformoutput', 0) %returns {'one' 'two' 'three'}
arrayfun(@(c) c(1), {'one' 'two' 'three'}); %returns {'one' 'two' 'three'}
However, if we want to do something during our manipulations, it's a little different. For example, we may want to extract the first character of each string. Compare the results of cellfun
and arrayfun
here:
cellfun( @(c) c(1), {'one' 'two' 'three'}, 'uniformoutput', 0); %returns {'o' 't' 't'}
arrayfun(@(c) c(1), {'one' 'two' 'three'}); %Returns {'one' 'two' 'three'}
Do get the same result with arrayfun, we need to dereference the cell within the anonymous function, and then extract the character, and then put the results into a cell array rather than a character array. Like this:
arrayfun(@(c) c{1}(1), {'one' 'two' 'three'},'uniformoutput',false) %Returns {'o' 't' 't'}
So the difference is that cellfun
takes care of the dereference operation which is required to do detailed operations on individual elements of a cell when looping (that is, the {}
), whereas arrayfun
just performs the standard indexing (that is, the ()
). In addition, the 'uniformoutput',false
notation determines if the output is written to a regular arral or a cell array.
To show what this means in code, see the following functions which are equivalent to cellfun
and arrayfun
, both with and without the 'uniformoutput',false
notation. These four functions are equivalent except for the use of the ()
vs. {}
within the loop:
function out = cellFunEquivalent(fn, x)
for ix = numel(x):-1:1
out(ix) = fn(x{ix});
end
out = reshape(out,size(x));
end
function out = arrayFunEquivalent(fn, x)
for ix = numel(x):-1:1
out(ix) = fn(x(ix));
end
out = reshape(out,size(x));
end
function out = cellFunEquivalent_nonuniform(fn, x)
for ix = numel(x):-1:1
out{ix} = fn(x{ix});
end
out = reshape(out,size(x));
end
function out = arrayFunEquivalent_nonuniform(fn, x)
for ix = numel(x):-1:1
out{ix} = fn(x(ix));
end
out = reshape(out,size(x));
end
For the example you posted, the arrayfun
function is actually operating on single element cells, and reconstructing a copy of those cells into another array of the same (cell) class (see arrayFunEquivalent
). The cellfun
operation is dereferencing each element of the input cell array and then reconstructing a copy of those strings into a cell array (see cellFunEquivalent_nonuniform
). When the input x
is a cell, these operations are equivalent.