Octave / Matlab: Hinzufügen neuer Elemente zu einem Vektor

75

Mit einem Vektor muss xich ein Element hinzufügen ( newElem).

Gibt es einen Unterschied zwischen -

x(end+1) = newElem; 

und

x = [x newElem];

?

URL87
quelle

Antworten:

93

x(end+1) = newElem ist etwas robuster.

x = [x newElem]funktioniert nur x, wenn es sich um einen Zeilenvektor handelt, wenn es sich um einen Spaltenvektor handelt x = [x; newElem]. x(end+1) = newElemFunktioniert jedoch sowohl für Zeilen- als auch für Spaltenvektoren.

Im Allgemeinen sollten jedoch wachsende Vektoren vermieden werden. Wenn Sie dies häufig tun, wird Ihr Code möglicherweise gecrawlt. Denken Sie darüber nach: Um ein Array zu vergrößern, müssen Sie neuen Speicherplatz zuweisen, alles kopieren, das neue Element hinzufügen und das alte Durcheinander beseitigen ... Eine ziemliche Zeitverschwendung, wenn Sie vorher die richtige Größe kannten :)

ThijsW
quelle
3
Auch für die zweite Methode xmuss zuerst initialisiert werden!
Dan
1
@RodyOldenhuis, kein Problem! Ich habe das gleiche getan, wahrscheinlich zur gleichen Zeit. @ Dan, das stimmt, aber als die Frage "einen Vektor x(von Größe n) haben" erwähnte , nahm ich an n, dass er nicht Null ist und der Vektor bereits initialisiert wurde :)
ThijsW
1
@ThijsW: Dennoch ist die Verwendung endanstelle einer Variablen n(die globalnach allem, was Sie wissen , eine sein könnte !) Der universellere, robustere und kostengünstigere Weg
Rody Oldenhuis,
@Dan x muss für beide Methoden initialisiert werden.
Robino
@Robino Ich glaube nicht, ich habe kein MATLAB zu überprüfen, aber in der Oktave können Sie sicherlich x(end+1)=...ohne xInitialisierung auskommen und ich bin fast sicher, dass Sie es auch in MATLAB tun können
Dan
28

Um die Antwort von @ ThijsW zu ergänzen, bietet die erste Methode einen erheblichen Geschwindigkeitsvorteil gegenüber der Verkettungsmethode:

big = 1e5;
tic;
x = rand(big,1);
toc

x = zeros(big,1);
tic;
for ii = 1:big
    x(ii) = rand;
end
toc

x = []; 
tic; 
for ii = 1:big
    x(end+1) = rand; 
end; 
toc 

x = []; 
tic; 
for ii = 1:big
    x = [x rand]; 
end; 
toc

   Elapsed time is 0.004611 seconds.
   Elapsed time is 0.016448 seconds.
   Elapsed time is 0.034107 seconds.
   Elapsed time is 12.341434 seconds.

Ich habe diese Zeiten in 2012b ausgeführt, aber als ich den gleichen Code auf demselben Computer in matlab 2010a ausgeführt habe, den ich bekomme

Elapsed time is 0.003044 seconds.
Elapsed time is 0.009947 seconds.
Elapsed time is 12.013875 seconds.
Elapsed time is 12.165593 seconds.

Ich denke, der Geschwindigkeitsvorteil gilt nur für neuere Versionen von Matlab

Dan
quelle
+1, bearbeitet, um auch das Offensichtliche hinzuzufügen. Ich werde noch einmal auf einer "echten" CPU testen (ich bin jetzt auf dieser beschissenen unzuverlässigen, nicht guten APU-Sache ...)
Rody Oldenhuis
Dort, jetzt alles besser :)
Rody Oldenhuis
@ Dan, das gleiche für mich, ich bekomme 0,028 für die 3. Option und 8,909 für die letzte
ThijsW
1
Ich denke auch, dass die JIT-Optimierung für den x(end+1)Fall eine ziemlich neue Ergänzung ist (R2012a oder so ...). Ich erinnere mich vage daran, dass ich so etwas in einigen Changenotes am Smoe Point gelesen habe. Ich bekomme auch sehr unterschiedliche Ergebnisse auf meiner APU / Matlab R2010, aber ich bin nicht sicher, ob das an der Matlab-Version oder der APU liegt ...
Rody Oldenhuis
@ RodyOldenhuis und ThiijsW sehen meinen jüngsten Vergleich zwischen älterem und neuerem Matlab
Dan
4

Wie bereits erwähnt, hat die Verwendung von x(end+1) = newElemden Vorteil, dass Sie Ihren Vektor mit einem Skalar verketten können, unabhängig davon, ob Ihr Vektor transponiert ist oder nicht. Daher ist es robuster für das Hinzufügen von Skalaren.

Was jedoch nicht vergessen werden sollte, ist, dass dies x = [x newElem]auch funktioniert, wenn Sie versuchen, mehrere Elemente gleichzeitig hinzuzufügen. Darüber hinaus verallgemeinert sich dies etwas natürlicher auf den Fall, in dem Sie Matrizen verketten möchten.M = [M M1 M2 M3]


Alles in allem, wenn Sie eine Lösung wollen , dass Sie Ihre bestehenden Vektor verketten ermöglicht xmit , newElemdass kann oder auch nicht ein Skalar sein kann, sollte dies den Trick:

 x(end+(1:numel(newElem)))=newElem
Dennis Jaheruddin
quelle
1
Ich denke, Ihr letztes Beispiel sollte sein: x (Ende + 1: Ende + Länge (newElem)) = newElem
Digna
@Digna Vielen Dank, dass Sie den Fehler gefunden haben. Ich habe die Antwort aktualisiert, um das Problem zu beheben.
Dennis Jaheruddin
1
Bei meinem Matlab2011b gab es auch eine drastische (~ 50-fache) Geschwindigkeitsverbesserung der Vektorkettung mit dieser Methode im Vergleich zur a = [ab] -Methode.
JaBe
@Jabe die [ab] Methode ist Verkettung. Ich nehme an, Sie sagen, dass das Erweitern des Arrays schneller ist als die Verkettung?
Robino