Hier ist eine Frage darüber, ob wir den Operationstyp der Vektorisierung in Matlab verwenden können, um das Schreiben für die Schleife zu vermeiden.
Ich habe einen Vektor
%Vor% Ich erzeuge einen gleichmäßig verteilten Zufallsvektor über [0,1)
Ich möchte wissen, ob jeder Eintrag von X
zwischen [0,0.1)
oder [0.1,0.3)
oder [0.3,0.6)
oder [0.6,1.0)
liegt, und ich möchte einen Vektor zurückgeben, der den Index des maximalen Elements in% co_de enthält %, dass jeder Eintrag von Q
kleiner als ist.
Ich könnte eine for-Schleife schreiben
%Vor%Erwartetes Ergebnis für dieses Beispiel:
%Vor%Aber ich frage mich, ob es eine Möglichkeit gibt, das Schreiben für eine Schleife zu vermeiden? (Ich sehe viele sehr gute Antworten auf meine Frage. Vielen Dank! Nun, wenn wir einen Schritt weiter gehen, was ist, wenn mein Q eine Matrix ist, so dass ich überprüfen möchte, ob)
%Vor% Octave macht einen sauberen Vektorisierungstrick für Sie, wenn die Vektoren, die Sie haben, entlang verschiedener Dimensionen sind. Wenn Sie Q
zu einem Spaltenvektor machen, können Sie dies tun:
Das Ergebnis ist eine 6x4-Matrix, die angibt, welche Elemente von Q
jedes Element von X
kleiner als ist. Ich habe Q
eine andere Länge als X
gemacht, nur um dies zu verdeutlichen:
Gehen Sie zurück zum ursprünglichen Beispiel, das Sie haben, können Sie
tun %Vor%um
zu erhalten %Vor% Beachten Sie, dass ich in der Definition von Q
Semikolons anstelle von Kommas habe. Wenn Sie nach der Definition einen Spaltenvektor erstellen möchten, tun Sie stattdessen Folgendes:
Der Grund dafür ist, dass Octave bsxfun
implizit auf eine Operation in einem Zeilen- und Spaltenvektor anwendet. MATLAB wird dies nicht nach R2016b gemäß dem @ excaza-Kommentar tun, daher können Sie dies in MATLAB tun:
Sie können dieses Beispiel in IDEOne hier ausprobieren.
Verwenden Sie die zweite Ausgabe von max
, die als eine Art "Vektorisierung" fungiert find
":
Wie das funktioniert :
X
, ob es kleiner als jedes Element von Q
ist. Dies geschieht mit bsxfun(@lt, X(:).', Q(:))
. Beachten Sie, dass jede Spalte im Ergebnis einem Element von X
und jede Zeile einem Element von Q
. X
den Index des ersten Elements von Q
, für den dieser Vergleich true
ist. Dies geschieht mit [~, Y] = max(..., [], 1)
. Beachten Sie, dass die zweite Ausgabe von max
den Index des ersten Maximizers (entlang der angegebenen Dimension) zurückgibt. In diesem Fall wird der Index des ersten true
in jeder Spalte angegeben. Für Ihre Beispielwerte
%Vor%gibt
%Vor% Die Verwendung von bsxfun
hilft dabei. Sie müssen darüber lesen. Ich fügte auch einen Q = 0 am Anfang hinzu, um den kleinen X Fall
% output ist 2 4 3 4 1
BEARBEITEN: Wie lange dauert jede Methode?
Ich wurde neugierig auf den Unterschied zwischen jeder Lösung:
Testcode unten:
%Vor%Führen Sie es für sich selbst, fand ich, dass, wenn die Größe von X 1e6 war, bsxfun viel schneller war, während für kleinere Arrays die Unterschiede variierten und vernachlässigbar waren.
BEISPIEL: wenn Größe X 1e3 war
%Vor% Octave hat genau die Funktion lookup
. Es benötigt eine Nachschlagetabelle mit sortierten Werten und einem Array und gibt ein Array mit Indizes für Werte in der Nachschlagetabelle zurück.
Das einzige Problem ist, dass Ihre Nachschlagetabelle eine implizite Null hat, die einfach mit:
behoben werden kann %Vor% Sie können eine anonyme Funktion erstellen, um den Vergleich durchzuführen, und sie dann mit arrayfun
:
Das Q-Array wird in der anonymen Funktion ( compareFunc
) gespeichert, wenn die anonyme Funktion erstellt wird.
Oder als eine Zeile (Uniform Output ist das Standardverhalten von arrayfun):
%Vor%Inspiriert von der Lösung von @Mad Physicist, hier ist meine Lösung.
%Vor%Die Idee ist, dass Sie X und Q in die "gleiche Form" bringen, dann einen elementweisen Vergleich verwenden, dann erhalten wir eine logische Matrix, deren Zeile angibt, ob ein gegebenes Element in X kleiner ist als jedes Element in Q. dann gebe den ersten von Null verschiedenen Index jeder Reihe dieser logischen Matrix zurück. Ich habe nicht getestet, wie schnell diese Methode mit anderen Methoden verglichen wird
Tags und Links loops matlab octave vectorization