我想定义一个接受一个向量的匿名函数,但是除非指定向量中的每个元素,否则我无法实现这一点:
Data =
[ X11 X12;
X21 X22];
迭代#1:V -> [X11 X12]
(在每次迭代时传递给'some_func'的期望行值)。迭代#2:V -> [X21 X22]
如此:
good_func_handle = @(a1,a2) some_func([a1,a2],bla,bla)
output = arrayfun(good_func_handle,Data(:,1),Data(:,2)) -> to avoid having to write a for loop
这行不通:
bad_func_handle = @(vec) some_func(vec,bla,bla)
output = arrayfun(bad_func_handle,Data)
当调用时,只有第一个元素X11
被传递给some_func
,而不是X11
和X12
。
是否有一种方法可以将函数设置为将向量变量作为输入,而不必指定向量中的所有元素?
问题是在arrayfun
,而不是在被调用的函数。arrayfun
循环遍历输入数组的每个元素,而不是每一行。在第一个解决方案中,您创建了输入数组,这样循环遍历每个元素是正确的。
由于arrayfun
只是一个循环,除了程序员的时间外,使用它在时间上没有任何优势。它只是为了简化在数组上编写循环。(资格:在MATLAB中,arrayfun
增加了开销,因为每次迭代都需要调用函数;这可能非常重要,如下所示。在Octave中,arrayfun
似乎比普通循环更有效,参见下面smcmi的注释。[/p]
为了回应@smcmi下面的评论,我重新创建了他们的实验如下:
a = zeros(1, 1e6);
b = method1(a);
c = method2(a);
assert(isequal(b,c))
timeit(@()method1(a))
timeit(@()method2(a))
function out = method1(in)
out = zeros(size(in));
for ii=1:numel(in)
out(ii) = in(ii) * 2;
end
end
function out = method2(in)
out = arrayfun(@(x) x * 2, in);
end
使用MATLAB Online运行此程序(通常非常慢),我看到以下输出:
ans =
0.0036
ans =
2.5299
也就是说,普通循环需要0.0036秒,而arrayfun
需要2.5秒。这是三个数量级的差别。
arrayfun
中最大的开销是为每个数组元素调用一个函数。在MATLAB中,调用函数仍然会带来一些开销,而JIT完全优化了循环,并且运行速度与任何编译语言相似。