Matlab 动态填充向量而不指定空矩阵
我经常需要在Matlab中动态填充向量。但是,这有点烦人,因为您首先必须定义一个空变量,例如:Matlab 动态填充向量而不指定空矩阵,matlab,Matlab,我经常需要在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 有没有更好的方法来实现这个“推送”功能,这样您就不必事先定义空向量了?人们告诉我
[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中是荒谬的-如果你认为是这样,请解释原因
相关:,在表达式的右侧使用变量之前,在MATLAB中不可能省略变量的初始化。此外,不希望忽略它,因为预分配数组几乎总是正确的方法
如中所述,即使元素的确切数量未知,也希望预先分配矩阵。为了证明这一点,需要一个小的基准:
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
此图显示了没有预分配的方法比基于最大可能返回大小预分配矩阵慢多少时间。请注意,由于指数行为,预分配对于大型矩阵尤其重要。在MATLAB中,预分配是一种方法。从:
for
和while
循环每次通过循环时都会增量增加数据结构的大小,这会对性能和内存使用产生不利影响
正如m7913d在评论中指出的那样,MathWorks的答案部分中有一个问题也解决了这一点
我建议“过度分配”内存,然后在循环后减小数组的大小
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=[]
还要糟糕!但是,与保存和使用更糟糕的代码相比,您最好多花几次按键和几分钟来编写结构良好的代码。与其构建一个空矩阵,不如尽可能地预先分配一个正确大小的矩阵。@m7913d我认为在这种情况下这是不可能的,因为随机性。但我不明白问题中“恼人”的意思。Matlab在声明和预分配的方式上非常舒适,在抱怨恼人的防御之前,您需要一些C编码……尽管最终a
的大小是随机的,但在这种情况下,您知道它不会大于10
。你可以做a=nan(10,1)
,然后是循环中的a(ind)=randi(5)
(不经常推到a
),最后是a=a(~isnan(a))
删除原始的NaN
值。在内存上可能更友好(假设阵列不是很大)@m7913d啊,我刚刚免费下载了它,很高兴能在Central上备份@rahnema1检查现有代码确实是一种可能性,但会产生更多(ennoying)代码。OP的目标是尽可能地限制它。