2010-04-14 18 views
36

Ich habe einen Vektor zum BeispielWie Nullkomponenten in einem Vektor in Matlab löschen?

a = [0 1 0 3] 

ich in b drehen will, die b = [1 3] entspricht.

Wie führe ich das generell durch? Also habe ich einen Vektor mit einigen Null-Komponenten und ich möchte die Nullen entfernen und nur die Nicht-Null-Zahlen lassen?

Antwort

79

Wenn Sie nur die Nullen entfernen möchten, die Nicht-Nullen hinter in eine Abgangs, dann ist die beste Lösung

a(a==0) = []; 

Dies löscht die Null-Elemente, eine logische Indizierung Ansatz in MATLAB. Wenn der Index für einen Vektor ein boolescher Vektor ist, der dieselbe Länge wie der Vektor hat, kann MATLAB dieses boolesche Ergebnis verwenden, um es mit zu indizieren. So ist dies äquivalent zu

a(find(a==0)) = []; 

Und, wenn Sie einige Array-Elemente auf [] in MATLAB gesetzt, die Konvention ist es, sie zu löschen.

Wenn Sie die Nullen in ein neues Ergebnis b setzen wollen, während eine unverändert bleiben, der beste Weg, wahrscheinlich

b = a(a ~= 0); 

ist Wiederum ist logische Indizierung hier verwendet. Sie könnten die entsprechende Version (in Bezug auf das Ergebnis) von

b = a(find(a ~= 0)); 

aber mlint wird am Ende des Markieren Sie die Zeile als einen, wo der rein logische Index war effizienter und damit besser geeignet verwendet.

Wie immer, achten Sie auf EXACT-Tests für Null oder für eine beliebige Anzahl, wenn Sie Elemente einer akzeptiert hätten, die innerhalb einiger Epsilon Toleranz von Null waren. Haben diese Tests wie diese

b = a(abs(a) >= tol); 

Diese behält nur die Elemente einer, die mindestens so groß wie Ihre Toleranz sind.

+1

oder für das erste Beispiel, a = a (a ~ = 0) 'ist ausreichend, die In-Place-Zuweisung funktioniert gut. Guter Punkt beim Testen gegen eine kleine Zahl statt 0. – mtrw

+0

@woodchips: Habe gerade einen Leistungsvergleich unten gepostet :) – tim

3
b = a(find(a~=0)) 
+2

nur 'b = a (find (a))' ist ausreichend, der Standardwert ist, Nicht-Null-Werte zu finden. – wich

+5

oder 'b = a (a ~ = 0)' ist ausreichend, logische Indizierung ist impliziert. – mtrw

+1

Gute Kommentare, ich fühle mich schlecht, meine schlechte Antwort upvoted bekommen. –

8

Ich kam gerade über dieses Problem und wollte etwas über die Leistung finden, aber ich konnte nicht, so schrieb ich ein Benchmarking-Skript auf meinem eigenen:

% Config: 
rows = 1e6; 
runs = 50; 

% Start: 
orig = round(rand(rows, 1)); 

t1 = 0; 
for i = 1:runs 
    A = orig; 
    tic 
    A(A == 0) = []; 
    t1 = t1 + toc; 
end 
t1 = t1/runs; 

t2 = 0; 
for i = 1:runs 
    A = orig; 
    tic 
    A = A(A ~= 0); 
    t2 = t2 + toc; 
end 
t2 = t2/runs; 

t1 
t2 
t1/t2 

Sie sehen also, die Lösung A = A(A ~= 0) mit ist der schnellere der beiden :)

4

Ich endete oft Dinge wie diese. Daher habe ich versucht, eine einfache Funktion zu schreiben, die die unerwünschten Elemente auf einfache Weise "ausschneidet". Damit wird Matlab Logik den Kopf ein wenig nach unten, aber sieht gut aus:

b = snip(a,'0') 

Sie die Funktion Datei auf finden: http://www.mathworks.co.uk/matlabcentral/fileexchange/41941-snip-m-snip-elements-out-of-vectorsmatrices

Es funktioniert auch mit allen anderen ‚x‘, nan oder was auch immer Elemente.

+6

Das ist ein mächtiger Hammer, der eine winzige kleine Fliege ... – Shai

2

Warum nicht einfach, a=a(~~a) oder a(~a)=[]. Es entspricht den anderen Ansätzen, aber sicherlich weniger Tastenanschlägen.

2

Daten

a=[0 3 0 0 7 10 3 0 1 0 7 7 1 7 4] 

Do

aa=nonzeros(a)' 

Ergebnis

aa=[3 7 10 3 1 7 7 1 7 4] 
+0

Warum macht man diesen Beitrag nicht besser: füge einen Link zu die Dokumentation und verwenden richtige Hervorhebung für Ihren Code – Sjon

+0

Ich denke, das ist eine gute Antwort! Es wäre schön, einen Vergleich mit anderen Vorschlägen zu bekommen. –

2

Sie könnten spärlich verwenden (a), die

(1,2) 1

zurückkehren

(1,4) 3

Damit können Sie die Informationen darüber, wo Ihre Einträge ungleich Null waren, beibehalten.

Verwandte Themen