【问题标题】:Is there a better way to declare an empty, typed matrix in MATLAB?有没有更好的方法在 MATLAB 中声明一个空的类型化矩阵?
【发布时间】:2011-02-05 08:46:48
【问题描述】:

有没有办法在 MATLAB 中“声明”具有特定用户定义类型的变量? zeros() 仅适用于内置数字类型。我想出的唯一解决方案是使用 repmat() 将虚拟对象复制零次:

arr = repmat(myClass(), [1 0])

如果不以这种方式声明变量,任何执行“arr(end+1) = myClass()”的代码都必须包含一个特殊情况,即默认空矩阵类型为 double。

我是否错过了一些更明智的事情?

【问题讨论】:

    标签: matlab types matrix


    【解决方案1】:

    根据this documentation,所有类都有一个empty 方法,用于创建该类的空数组。例如:

    arr = myClass.empty(0,0);  %# Creates a 0-by-0 array of class myClass
    

    built-in types 也是如此:

    a = uint8.empty(0,1);   %# A 0-by-1 uint8 array
    b = single.empty(5,0);  %# A 5-by-0 single array
    c = cell.empty(0,0);    %# A 0-by-0 cell array
    


    关于预分配的说明...

    您提到您将通过以下方式循环增长此数组:

    arr(end+1) = myClass();
    

    如果您知道数组的最终大小是多少,通常在循环外preallocate the entire array 然后覆盖或修改循环中的数组元素会更有效。我将在an answer to another question 中讨论如何为用户定义的类执行此操作。

    【讨论】:

      【解决方案2】:

      这就是我使用的。您可以使用采用标量大小参数的稍微简洁的形式。

      r = repmat(MyClass, 0);
      

      请注意,您并没有将变量声明为具有类型;它仍然只是具有类型的变量中保存的值。

      这适用于旧样式和新 MCOS 类。如果您使用所有新样式类,gnovice 的“empty()”听起来是个好主意。


      如果您感觉先进,还有另一种选择,为了完整起见,我将其包括在内。

      您也可以在 subsasgn 中为您的对象处理这个问题,至少对于老式的 Matlab 类。如果您使用 RHS 上的用户定义对象(“右手边”)对未初始化的变量进行索引赋值,则该类的 subsagn 将被调用,LHS 以 [](空双精度)形式出现。如果你有一个特殊的构造函数形式,允许你构造一个空对象而不调用对象上的 repmat,你可以支持这一点,这样用户就不必用你的类的对象预先分配他们的变量。

      在你的 subsasgn 中:

      function obj = subsasgn(obj, S, B)
      ...
      s = S(1);
      ...
      switch s.type
          case '()'
              % Handle dispatch on LHS autovivification
              if isnumeric(obj) && isa(B, mfilename('class'))
                  % Must use special ctor to preallocate
                  obj = feval(class(B), mxdims(size(B)));
              end
      

      然后在你的构造函数中,有一个后门调用表单,用于通过祝福预先重新格式化的结构来构造空。

      function MyClass(varargin) %constructor
      
      SuperClasses = { }; % if you inherit, fill this in
      
      if nargin == 1 && isa(varargin{1}, 'mxdims')
         % special backdoor to support preallocation without repmat
         s = repmat(DataStructure, msize(varargin{1})); % built-in repmat called on plain struct
         out = class(s, mfilename, SuperClasses{:});
         return;
      end
      ...
      

      @mxdims 类是您需要创建的一个特殊类,它包含一个大小向量并用作调用此后门表单的标记。 msize() 方法返回它所代表的大小向量。

      如果您定义 MyClass 以便它支持这一点,那么您可以只执行“s(1) = MyClass”而不预先分配 s。但是你不能做“s(end+1)”; "end" 仅适用于预先分配的值。

      这是 Matlab 的一个棘手领域。在 subsasgn 和类似的类型系统中工作会产生很多细微的错误,包括段错误。这样做会让您为用户定义的对象获得更“完整”的行为。但这涉及工作和脆弱性,您最好坚持使用“repmat(class, 0)”或“empty()”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-22
        • 2010-11-25
        • 1970-01-01
        • 2011-05-14
        • 2014-10-23
        • 2011-09-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多