2009-02-26 13 views
4

ich oft gefunden habe ich so etwas wie dies zu tun:Wie kann ich einen nicht numerischen Vektor in MATLAB vorallokieren?

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 

, die zwar funktional, nicht optimal ist - der processedData Vektor innerhalb der Schleife wächst. Sogar mlint warnt mich, dass ich eine Vorabzuweisung für die Geschwindigkeit in Betracht ziehen sollte.

Daten wurden ein Vektor von int8, konnte ich dies tun:

% preallocate processed data array to prevent growth in loop 
processedData = zeros(length(unprocessedData), 1, 'int8'); 

und die Schleife ändern Vektor-Slots statt verketten zu füllen.

Gibt es eine Möglichkeit, einen Vektor vorzubelegen, so dass er anschließend Strukturen oder Objekte aufnehmen kann?


Update: von Azim's answer inspiriert, ich habe einfach die Schleife Reihenfolge umgekehrt. erste Kräfte Vorbelegung des gesamten Vektors in dem ersten Treffer die letzte Elements der Verarbeitung, wie der Debugger bestätigt:

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 

Dies erfordert, dass alle Objekte, die von process() einen gültigen Null-args Konstruktor zurückgegeben seit MATLAB initialisiert processedData auf das erste Schreiben mit realen Objekten.

mlint klagt noch über mögliche Array Wachstum, aber ich denke, das ist, weil es die umgekehrte Schleifeniterationslatenzzeit nicht erkennen kann ...

Antwort

3

Da Sie die Felder der Struktur processedData kennen und Sie wissen, seine Länge, eine Möglichkeit, wäre folgendes:

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 

Dies setzt voraus, dass die process Funktion eine Struktur mit den gleichen Feldern wie processedData zurückgibt.

4

Neben Azim's answer, eine andere Möglichkeit, dies zu tun, ist mit repmat:

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

wo nElements die Anzahl der Elemente, die Sie in der Struktur oder ein Objekt-Array haben.

ACHTUNG: Wenn das Objekt, das Sie erstellen, von handle class abgeleitet ist, werden Sie das Objekt selbst nicht replizieren, behandeln Sie nur Verweise darauf. Abhängig von Ihrer Implementierung müssen Sie möglicherweise die Objektkonstruktormethode nElements mal aufrufen.

+0

+1 Dies ist eine Situation, für die repmat nützlich ist. – Azim

3

Sie können in einem Zellenfeld struct der entsprechenden Größe passieren:

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

Dies wird eine Struktur Array machen, die die gleiche Größe wie die Zellenmatrix ist.

+0

+1 Dies ist eine gute Alternative für die Erstellung von Struktur-Arrays, besonders wenn Sie bereits Zellen-Arrays von Daten haben, mit denen Sie die Felder füllen wollen. – gnovice

Verwandte Themen