我经常需要在Matlab中动态填充向量。然而,由于您首先必须首先定义一个空变量,例如:
,因此这很烦人[a,b,c]=deal([]);
for ind=1:10
if rand>.5 %some random condition to emphasize the dynamical fill of vector
a=[a, randi(5)];
end
end
a %display result
有没有更好的方法来实现这个'推送'函数,以便您不必事先定义空向量?人们告诉我这在Matlab中是荒谬的 - 如果您认为是这种情况,请解释原因。
相关:Push a variable in a vector in Matlab,is-there-an-elegant-way-to-create-dynamic-array-in-matlab
答案 0 :(得分:2)
在MATLAB中,预分配是最佳选择。来自docs:
每次循环时,逐步增加数据结构大小的
for
和while
循环会对性能和内存使用产生负面影响。
正如m7913d的评论所指出的那样,MathWorks的答案部分提出了一个问题,该问题涉及同一点read it here。
我建议“过度分配”内存,然后在循环后减小数组的大小。
numloops = 10;
a = nan(numloops, 1);
for ind = 1:numloops
if rand > 0.5
a(ind) = 1; % assign some value to the current loop index
end
end
a = a(~isnan(a)); % Get rid of values which weren't used (and remain NaN)
不,这不会减少你在循环之前写的数量,它甚至比写a = []
还要糟糕!但是,你最好花一些额外的击键时间和分钟编写结构良好的代码而不是进行保存并使代码更差。
答案 1 :(得分:1)
在MATLAB中,不可能在表达式的右侧使用变量之前省略变量的初始化。此外,不希望省略它,因为预分配数组几乎总是正确的方法。
正如this post中所提到的,即使不知道确切的元素数量,甚至还需要预先分配矩阵。为了证明这一点,需要一个小的基准:
Ns = [1 10 100 1000 10000 100000];
timeEmpty = zeros(size(Ns));
timePreallocate = zeros(size(Ns));
for i=1:length(Ns)
N = Ns(i);
timeEmpty(i) = timeit(@() testEmpty(N));
timePreallocate(i) = timeit(@() testPreallocate(N));
end
figure
semilogx(Ns, timeEmpty ./ timePreallocate);
xlabel('N')
ylabel('time_{empty}/time_{preallocate}');
% do not preallocate memory
function a = testEmpty (N)
a = [];
for ind=1:N
if rand>.5 %some random condition to emphasize the dynamical fill of vector
a=[a, randi(5)];
end
end
end
% preallocate memory with the largest possible return size
function a = testPreallocate (N)
last = 0;
a = zeros(N, 1);
for ind=1:N
if rand>.5 %some random condition to emphasize the dynamical fill of vector
last = last + 1;
a(last) = randi(5);
end
end
a = a(1:last);
end
此图显示没有预分配的方法比基于最大可能返回大小预分配矩阵的时间慢。请注意,由于指数行为,预分配对于大型矩阵尤其重要。