如何在MATLAB中预分配一个非数值向量?

5

我经常发现自己做类似这样的事情:

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在第一次写入实际对象时会初始化processedDatamlint仍然会发出可能的数组增长的警告,但我认为这是因为它无法识别反向循环迭代...
3个回答

5
除了Azim的回答之外,另一种方法是使用repmat
% Make a single structure element:
processedData = struct('field1',[],'field2',[]);
% Make an object:
processedData = object_constructor(...);
% Replicate data:
processedData = repmat(processedData,1,nElements);

其中nElements是结构体或对象数组中元素的数量。

注意:如果您创建的对象派生自句柄类, 您将不会复制对象本身,而只是复制对其的句柄引用。根据您的实现方式,您可能需要调用对象构造方法nElements次。


3

既然你已经了解了结构体 processedData 所包含的域以及其长度,那么一种方法是:

unprocessedData = fetchData();
processedData = struct('field1', [], ...
                       'field2', []) % create the processed data struct
processedData(length(unprocessedData)) = processedData(1); % create an array with the required length
for dataIdx = 1:length(unprocessedData)
    processedData(dataIdx) = process(unprocessedData(dataIdx));
end

这假设process函数返回一个与processedData具有相同字段的结构体。

3
您可以将一个单元数组传递给大小合适的struct函数:
processedData = struct('field1', cell(nElements, 1), 'field2', []);

这将生成一个结构数组,大小与单元数组相同。

+1 如果你已经有了要填充字段的单元数组数据,那么这是一个很好的结构数组替代方案。 - gnovice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接