Есть ли лучший способ объявить пустую типизированную матрицу в MATLAB? - PullRequest
5 голосов
/ 07 апреля 2010

Есть ли способ "объявить" переменную с определенным пользователем типом в MATLAB? Нули () работают только для встроенных числовых типов. Единственное решение, которое я придумала, заключается в использовании repmat () для дублирования фиктивного объекта ноль раз:

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

Без объявления переменных таким образом, любой код, который выполняет "arr (end + 1) = myClass ()", должен включать специальный случай для пустой матрицы по умолчанию, которая имеет тип double.

Я пропустил что-то более разумное?

Ответы [ 2 ]

6 голосов
/ 07 апреля 2010

Согласно этой документации , все классы имеют метод empty, который создает пустые массивы этого класса. Например:

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

Это также верно для встроенных типов :

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();

Если вы знаете, какой будет окончательный размер массива, обычно более эффективно предварительно выделить весь массив вне цикла, а затем перезаписать или изменить элементы массива в цикле. Я обсуждаю, как вы можете сделать это для пользовательских классов в ответе на другой вопрос .

2 голосов
/ 07 апреля 2010

Вот что я использую.Вы можете использовать более краткую форму, которая принимает аргумент скалярного размера.

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 (конец + 1)", хотя;«end» работает только с предварительно выделенными значениями.

Это сложная область Matlab, с которой нужно работать. Работа в subsasgn и подобной системе типов может привести к множеству незначительных ошибок, в том числе к ошибкам сегмента.Делая это таким образом, вы получите более «полное» поведение для ваших пользовательских объектов.Но это включает в себя работу и хрупкость, и вам, вероятно, лучше придерживаться «repmat ( class , 0)» или «empty ()».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...