使用arrayfun在每个组合上应用函数的两个参数

时间:2015-05-10 15:04:22

标签: octave vectorization

允许i = [1 2]j = [3 5]。现在是八度:

arrayfun(@(x,y) x+y,i,j)

我们得到[4 7]。但我想在ij的组合上应用该函数来获取[i(1)+j(1) i(1)+j(2) i(2)+j(1) i(2)+j(2)]=[4 6 5 7]

我如何做到这一点?我知道我可以使用for-loopsl但我想要矢量化代码,因为它更快。

2 个答案:

答案 0 :(得分:1)

首先,你的第一个例子并不是最好的,因为用arrayfun完成你所做的事情最有效的方法就是矢量化:

a = [1 2];
b = [3 5];
out = a+b

其次,至少在Matlab中,arrayfun不一定比简单的for循环更快。 arrayfun主要是一种便利(特别是对于它更高级的选项)。请亲自尝试这个简单的计时示例:

a = 1:1e5;
b = a+1;

y = arrayfun(@(x,y)x+y,a,b); % Warm up
tic
y = arrayfun(@(x,y)x+y,a,b);
toc

y = zeros(1,numel(a));
for k = 1:numel(a)
    y(k) = a(k)+b(k); % Warm up
end
tic
y = zeros(1,numel(a));
for k = 1:numel(a)
    y(k) = a(k)+b(k);
end
toc

在Matlab R2015a中,for循环方法从命令窗口运行速度快70倍,从M文件函数运行速度快260多倍。八度可能不同,但你应该试验。

最后,您可以使用meshgrid完成所需内容:

a = [1 2];
b = [3 5];
[x,y] = meshgrid(a,b);
out = x(:).'+y(:).'

会在您的问题中返回[4 6 5 7]。您还可以使用ndgrid以不同的顺序获取输出。

答案 1 :(得分:1)

在Octave中,为了找到两个向量之间的求和,您可以使用真正的向量化方法broadcasting,如此 -

out = reshape(ii(:).' + jj(:),[],1)

这是ideone对每个大小为1 x 100的输入向量的运行时测试 -

-------------------- With FOR-LOOP
Elapsed time is 0.148444 seconds.
-------------------- With BROADCASTING
Elapsed time is 0.00038299 seconds.

如果你想保持它的通用性以适应除了汇总之外的操作,你可以使用像这样的匿名函数 -

func1 = @(I,J) I+J;
out = reshape(func1(ii,jj.'),1,[])

在MATLAB中,您可以使用下面列出的两个bsxfun替代方案来完成相同的操作。

予。带有匿名函数的bsxfun -

func1 = @(I,J) I+J;
out = reshape(bsxfun(func1,ii(:).',jj(:)),1,[]);

II。 bsxfun内置@plus -

out = reshape(bsxfun(@plus,ii(:).',jj(:)),1,[]);

对于每个大小为1 x 10000的输入向量,我的运行时间为 -

-------------------- With FOR-LOOP
Elapsed time is 1.193941 seconds.
-------------------- With BSXFUN ANONYMOUS
Elapsed time is 0.252825 seconds.
-------------------- With BSXFUN BUILTIN
Elapsed time is 0.215066 seconds.