这是有趣的。您的示例正在执行两种不同的操作,这恰好导致相同的结果。探索起来很有趣。
TL;博士。arrayfun
当您的输入是一个数组,并且当您的输入是一个单元格时,您通常应该使用cellfun
,尽管您通常可以强制arrayfun
执行这项工作,并使用不同级别的语法地狱。
从根本上说,arrayfun
它旨在对阵列进行操作,并且cellfun
旨在对单元进行操作。但是,Matlab-wise 会注意到一个单元只不过是一个“单元”数组,所以arrayfun
无论如何都可以工作。
正如您所指出的,以下两行执行相同的操作:
cellfun(@(c) c, {'one' 'two' 'three'}, 'uniformoutput', 0) %returns {'one' 'two' 'three'}
arrayfun(@(c) c(1), {'one' 'two' 'three'}); %returns {'one' 'two' 'three'}
但是,如果我们想在操作过程中做某事,那就有点不同了。例如,我们可能想要提取每个字符串的第一个字符。比较cellfun
和arrayfun
这里的结果:
cellfun( @(c) c(1), {'one' 'two' 'three'}, 'uniformoutput', 0); %returns {'o' 't' 't'}
arrayfun(@(c) c(1), {'one' 'two' 'three'}); %Returns {'one' 'two' 'three'}
使用arrayfun 得到相同的结果,我们需要在匿名函数中取消引用单元格,然后提取字符,然后将结果放入单元格数组而不是字符数组中。像这样:
arrayfun(@(c) c{1}(1), {'one' 'two' 'three'},'uniformoutput',false) %Returns {'o' 't' 't'}
因此,不同之处在于它cellfun
负责在循环时对单元格的各个元素执行详细操作所需的取消引用操作(即{}
),而arrayfun
只执行标准索引(即()
)。此外,'uniformoutput',false
符号确定输出是否写入常规阵列或单元阵列。
要显示这在代码中的含义,请参阅以下等效于cellfun
and的函数arrayfun
,无论有无'uniformoutput',false
符号。除了在循环中使用()
vs.之外,这四个函数是等价的:{}
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
对于您发布的示例,该arrayfun
函数实际上是对单个元素单元格进行操作,并将这些单元格的副本重建为同一(单元格)类的另一个数组(请参阅 参考资料arrayFunEquivalent
)。该cellfun
操作取消引用输入元胞数组的每个元素,然后将这些字符串的副本重建为元胞数组(请参阅 参考资料cellFunEquivalent_nonuniform
)。当输入x
是一个单元格时,这些操作是等价的。