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

Using arrayfun to apply two arguments of a function on every combination

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,但我想要矢量化代码,因为它更快。

首先,您的第一个示例不是最好的,因为完成您使用 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 循环方法比命令 window 快 70 倍 运行 并且当 运行 从 M-档案功能。八度可能不同,但您应该尝试一下。

最后,您可以使用 meshgrid 完成您想要的:

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

which returns [4 6 5 7] 如你的问题。您还可以使用 ndgrid 以不同的顺序获取输出。

在 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,[]);

二. 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.