如何在 MATLAB 中预分配非数值向量?
我经常发现自己在做这样的事情:
unprocessedData = fetchData(); % returns a vector of structs or objects
processedData = []; % will be full of structs or objects
for dataIdx = 1 : length(unprocessedData)
processedDatum = process(unprocessedData(dataIdx));
processedData = [processedData; processedDatum];
end
虽然功能正常,但并不是最佳的 - processedData
向量在循环内增长。 甚至 mlint
也警告我应该考虑预先分配以提高速度。
如果数据是 int8 向量,我可以这样做:
% preallocate processed data array to prevent growth in loop
processedData = zeros(length(unprocessedData), 1, 'int8');
并修改循环以填充向量槽而不是连接。
有没有办法预先分配向量,以便它随后可以保存结构或对象?
更新: 灵感来自 Azim 的回答,我只是颠倒了循环顺序。 处理最后一个元素首先会强制在第一次命中中预分配整个向量,正如调试器所确认的:
unprocessedData = fetchData();
% note that processedData isn't declared outside the loop - this breaks
% it if it'll later hold non-numeric data. Instead we exploit matlab's
% odd scope rules which mean that processedData will outlive the loop
% inside which it is first referenced:
for dataIdx = length(unprocessedData) : -1 : 1
processedData(dataIdx) = process(unprocessedData(dataIdx));
end
这要求 process()
返回的任何对象都具有有效的零参数构造函数 因为 MATLAB 在第一次使用真实对象写入processedData
时初始化它。
mlint 仍然抱怨可能的数组增长,但我认为这是因为它无法识别反向循环迭代......
I've often found myself doing something like this:
unprocessedData = fetchData(); % returns a vector of structs or objects
processedData = []; % will be full of structs or objects
for dataIdx = 1 : length(unprocessedData)
processedDatum = process(unprocessedData(dataIdx));
processedData = [processedData; processedDatum];
end
Which, whilst functional, isn't optimal - the processedData
vector is growing inside the loop. Even mlint
warns me that I should consider preallocating for speed.
Were data a vector of int8
, I could do this:
% preallocate processed data array to prevent growth in loop
processedData = zeros(length(unprocessedData), 1, 'int8');
and modify the loop to fill vector slots rather than concatenate.
is there a way to preallocate a vector so that it can subsequently hold structs or objects?
Update: inspired by Azim's answer, I've simply reversed the loop order. Processing the last element first forces preallocation of the entire vector in the first hit, as the debugger confirms:
unprocessedData = fetchData();
% note that processedData isn't declared outside the loop - this breaks
% it if it'll later hold non-numeric data. Instead we exploit matlab's
% odd scope rules which mean that processedData will outlive the loop
% inside which it is first referenced:
for dataIdx = length(unprocessedData) : -1 : 1
processedData(dataIdx) = process(unprocessedData(dataIdx));
end
This requires that any objects returned by process()
have a valid zero-args constructor since MATLAB initialises processedData
on the first write to it with real objects.
mlint
still complains about possible array growth, but I think that's because it can't recognise the reversed loop iteration...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
除了Azim的回答之外,另一种方法是使用
repmat
:其中
nElements
是您将拥有的元素数量结构体或对象数组。注意:如果您创建的对象源自 句柄类 ,您不会复制对象本身,只需处理对其的引用。 根据您的实现,您可能必须调用对象构造函数方法
nElements
次。In addition to Azim's answer, another way to do this is using
repmat
:where
nElements
is the number of elements you will have in the structure or object array.BEWARE: If the object you are making is derived from the handle class, you won't be replicating the object itself, just handle references to it. Depending on your implementation, you might have to call the object constructor method
nElements
times.由于您知道结构体
processedData
的字段并且知道其长度,因此一种方法如下:假设
process
函数返回一个与以下字段具有相同字段的结构体:已处理数据
。Since you know the fields of the structure
processedData
and you know its length, one way would be the following:This assumes that the
process
function returns a struct with the same fields asprocessedData
.您可以将元胞数组传递给适当大小的 struct :
这将创建一个与元胞数组大小相同的结构体数组。
You can pass in a cell array to
struct
of the appropriate size:This will make a structure array that is the same size as the cell array.