使用 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]
。但我想将该函数应用于 i
与 j
的组合以获得 [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.
让i = [1 2]
和j = [3 5]
。现在八度:
arrayfun(@(x,y) x+y,i,j)
我们得到 [4 7]
。但我想将该函数应用于 i
与 j
的组合以获得 [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.