【问题标题】:How can I preallocate a non-numeric vector in MATLAB?如何在 MATLAB 中预分配非数字向量?
【发布时间】:2010-10-10 03:23:52
【问题描述】:

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

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's answer 的启发,我只是颠倒了循环顺序。正如调试器确认的那样,首先处理最后一个元素会强制在第一次命中时预分配整个向量:

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 仍然抱怨可能的数组增长,但我认为那是因为它无法识别反向循环迭代......

【问题讨论】:

    标签: matlab matlab-struct pre-allocation


    【解决方案1】:

    除了Azim's answer,另一种方法是使用repmat

    % Make a single structure element:
    processedData = struct('field1',[],'field2',[]);
    % Make an object:
    processedData = object_constructor(...);
    % Replicate data:
    processedData = repmat(processedData,1,nElements);
    

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

    注意:如果您正在创建的对象是从handle class 派生的,您将不会复制对象本身,只需处理对它的引用。根据您的实现,您可能需要调用对象构造方法nElements 次。

    【讨论】:

      【解决方案2】:

      由于您知道结构 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 这是制作结构数组的一个很好的替代方法,尤其是当您已经拥有要填充字段的数据元胞数组时。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-31
        • 1970-01-01
        • 2014-11-26
        • 1970-01-01
        • 2015-05-16
        • 2011-09-07
        • 2011-12-10
        相关资源
        最近更新 更多