2009-02-26 8 views
4

я часто себе делать что-то вроде этого:Как я могу предопределить нецифровой вектор в 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'); 

и изменить цикл для заполнения векторных слотов, а не СЦЕПИТЬ.

Есть ли способ предопределить вектор, чтобы впоследствии он мог удерживать структуры или объекты?


Update: вдохновлен 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 все еще жалуется на возможном росте массива, но я думаю, что это потому, что он не может распознать обращенные итерации цикла ...

ответ

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.

4

В дополнение к 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 является количество элементов, вы будете иметь в структуре или объекта массива.

BEWARE: Если объект, который вы делаете, является производным от handle class, вы не будете реплицировать сам объект, просто обрабатывайте ссылки на него. В зависимости от вашей реализации вам может потребоваться вызвать метод конструктора объекта nElements раз.

+0

+1 Это одна из ситуаций, для которой repmat полезен. – Azim

3

Вы можете передать в массив ячеек для struct соответствующего размера:

processedData = struct('field1', cell(nElements, 1), 'field2', []); 

Это позволит сделать структуру массива, имеет такой же размер, как массив ячеек.

+0

+1 Это хорошая альтернатива для создания структурных массивов, особенно если у вас уже есть массивы ячеек данных, которые вы хотите заполнить полями. – gnovice