这个问题在这里已有答案:
给定像a = [ -1; 0; 1];
这样的数组。对于每个a(i)
,我需要使用linspace(min(a(i),0),max(a(i),0),3);
计算线性间隔向量,其中每个linspace-vector应存储到矩阵中:
A = [-1 -0.5 0;
0 0 0;
0 0.5 1];
使用for循环,我可以这样做:
for i=1:3
A(i) = linspace(min(a(i),0),max(a(i),0),3);
end
如何在不使用循环的情况下实现此目的?
我能想到的最快的方法是计算步长,使用隐式二进制扩展从中构造向量。
a = [ -1; 0; 1];
n = 3;
stepsizes = (max(a,0)-min(a,0))/(n-1);
A = min(a,0) + (0:(n-1)).*stepsizes;
Timeit:
几个timeit
结果使用(使用timeit(@SO)
并删除块中的注释以进行定时):
function SO()
n = 1e3;
m = 1e5;
a = randi(9,m,1)-4;
% %Wolfie
% aminmax = [min(a, 0), max(a,0)]';
% A = interp1( [0,1], aminmax, linspace(0,1,n) )';
% %Nicky
% stepsizes = (max(a,0)-min(a,0))/(n-1);
% A = min(a,0) + (0:(n-1)).*stepsizes;
% %Loop
% A = zeros(m,n);
% for i=1:m
% A(i,:) = linspace(min(a(i),0),max(a(i),0),n);
% end
%Arrayfun:
A = cell2mat(arrayfun(@(x) linspace(min(x,0),max(x,0),n),a,'UniformOutput',false));
那么时间是:
arrayfun
:2.6298 s以a = [ -1; 0; 1]
为例。创建最小/最大数组:
aminmax = [min(a, 0), max(a,0)].';
现在使用interp1
N = 3; % Number of interpolation points.
b = interp1( [0,1], aminmax, linspace(0,1,N) ).';
>> b =
-1.0000 -0.5000 0
0 0 0
0 0.5000 1.0000
一种可能的解决方案是使用arrayfun
将函数应用于数组的每个元素。您还希望将结果转换为矩阵,因为输出位于单元数组中。由于arrayfun
的输出是非标量的,因此必须关闭均匀输出。
cell2mat(arrayfun(@(x) linspace(min(x,0),max(x,0),3),a,'UniformOutput',false))
编辑:我在100000长阵列上使用tic-toc方法进行了一些测试。我发现,arrayfun
的解决方案需要大约。比你建议用于循环的时间长1.5倍。
最快的方法是使用矩阵向量运算来计算所需的内容。例如,如果您只需要计算3个元素的linspace
,您可以使用以下内容:
[min(a(:),0), (max(a(:),0)+min(a(:),0))/2 ,max(a(:),0)];
您可以将此方法概括为linspace函数中的任意数量的元素(不一定只是3)。请注意,随着代码量的增加,可读性将受到影响:
j=4; % number of elements in each linspace
b=zeros(size(a,1),j); % create a solution matrix of size Nxj
b(:,1)=min(a(:),0); %first row
b(:,end)=max(a(:),0); % last row
temp=b(:,1)+b(:,end); % sum of the first and the last row
for i=2:j-1
b(:,i)=temp*(i-1)/(j-1); % fill in intermediate rows
end
注意,在这个方法中,我循环遍历每个linspace中的元素数,但不是通过数组a
。对于小j(在你的例子中就像j = 3),与循环遍历数组a
的方法相比,这将更快地工作(如果考虑像a=rand(100000,1)
这样的大型数组)。