Как я могу предварительно выделить нечисловой вектор в 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');
и измените цикл, чтобы заполнить векторные слоты, а не объединять.
Есть ли способ предварительно выделить вектор, чтобы впоследствии он мог содержать структуры или объекты?
Обновление: вдохновленный ответом Азима, я просто изменил порядок зацикливания. Обработка последнего элемента сначала вызывает предварительное выделение всего вектора в первом обращении, поскольку отладчик подтверждает:
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
,
В дополнение к ответу Азима, другой способ сделать это - использовать 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
раз.
Вы можете передать массив ячеек struct
соответствующего размера:
processedData = struct('field1', cell(nElements, 1), 'field2', []);
Это создаст структурный массив того же размера, что и массив ячеек.