Ich habe ein Problem. Ich muss jedes Element in einer n-dimensionalen Matrix in MATLAB durchlaufen. Das Problem ist, ich weiß nicht, wie ich das für eine beliebige Anzahl von Dimensionen machen soll. Ich weiß, ich kann sagen
for i = 1:size(m,1)
for j = 1:size(m,2)
for k = 1:size(m,3)
und so weiter, aber gibt es eine Möglichkeit, dies für eine beliebige Anzahl von Dimensionen zu tun?
Antworten:
Sie können die lineare Indizierung verwenden, um auf jedes Element zuzugreifen.
Dies ist nützlich, wenn Sie nicht wissen müssen, an welchem i, j, k Sie sich befinden. Wenn Sie jedoch nicht wissen müssen, an welchem Index Sie sich befinden, ist es wahrscheinlich besser, arrayfun () zu verwenden.
quelle
I = cell(1, ndims(array)); [I{:}] = ind2sub(size(array),idx);
.Die Idee eines linearen Index für Arrays in Matlab ist wichtig. Ein Array in MATLAB ist eigentlich nur ein Vektor von Elementen, die im Speicher aufgereiht sind. Mit MATLAB können Sie entweder einen Zeilen- und Spaltenindex oder einen einzelnen linearen Index verwenden. Beispielsweise,
Wir können die Reihenfolge sehen, in der die Elemente im Speicher gespeichert sind, indem wir das Array in einen Vektor abrollen.
Wie Sie sehen können, ist das 8. Element die Zahl 7. Tatsächlich gibt die Funktion find ihre Ergebnisse als linearen Index zurück.
Das Ergebnis ist, dass wir nacheinander auf jedes Element eines allgemeinen nd-Arrays mit einer einzigen Schleife zugreifen können. Wenn wir zum Beispiel die Elemente von A quadrieren wollten (ja, ich weiß, dass es bessere Möglichkeiten gibt, dies zu tun), könnte man dies tun:
Es gibt viele Umstände, unter denen der lineare Index nützlicher ist. Die Konvertierung zwischen dem linearen Index und zwei (oder höheren) dimensionalen Indizes erfolgt mit den Funktionen sub2ind und ind2sub.
Der lineare Index gilt im Allgemeinen für jedes Array in Matlab. Sie können es also für Strukturen, Zellenarrays usw. verwenden. Das einzige Problem mit dem linearen Index besteht darin, dass sie zu groß werden. MATLAB verwendet eine 32-Bit-Ganzzahl zum Speichern dieser Indizes. Wenn Ihr Array also mehr als 2 ^ 32 Elemente enthält, schlägt der lineare Index fehl. Es ist wirklich nur ein Problem, wenn Sie häufig spärliche Matrizen verwenden, wenn dies gelegentlich zu einem Problem führt. (Obwohl ich keine 64-Bit-MATLAB-Version verwende, glaube ich, dass das Problem für die glücklichen Menschen, die dies tun, gelöst wurde.)
quelle
x = ones(1,2^33,'uint8'); x(2^33)
funktioniert wie erwartet.Wie in einigen anderen Antworten ausgeführt, können Sie alle Elemente in einer Matrix
A
(beliebiger Dimension) mithilfe eines linearen Index von1
bisnumel(A)
in einer einzelnen for-Schleife durchlaufen. Es gibt auch einige Funktionen, die Sie verwenden können:arrayfun
undcellfun
.Nehmen wir zunächst an, Sie haben eine Funktion, die Sie auf jedes Element von
A
(aufgerufenmy_func
) anwenden möchten . Sie erstellen zunächst ein Funktionshandle für diese Funktion:Wenn
A
es sich um eine Matrix (vom Typ double, single usw.) mit beliebiger Dimension handelt, können Siearrayfun
siemy_func
auf jedes Element anwenden :Wenn
A
es sich um ein Zellenarray mit beliebiger Dimension handelt, können Siecellfun
Folgendesmy_func
auf jede Zelle anwenden :Die Funktion
my_func
mussA
als Eingabe akzeptieren . Wenn es Ausgänge von gibtmy_func
, werden diese platziertoutArgs
, die dieselbe Größe / Dimension wie habenA
.Eine Einschränkung bei Ausgängen ... Wenn
my_func
Ausgänge unterschiedlicher Größe und Art zurückgegeben werden, wenn sie mit verschiedenen Elementen von arbeitenA
,outArgs
muss dies zu einem Zellenarray gemacht werden. Dies erfolgt durch Aufrufen von entwederarrayfun
odercellfun
mit einem zusätzlichen Parameter / Wert-Paar:quelle
Ein weiterer Trick ist die Verwendung von
ind2sub
undsub2ind
. In Verbindung mitnumel
undsize
können Sie so etwas wie das Folgende tun, wodurch ein N-dimensionales Array erstellt wird und dann alle Elemente auf der "Diagonale" auf 1 gesetzt werden.quelle
Sie könnten eine rekursive Funktion veranlassen, die Arbeit zu erledigen
L = size(M)
idx = zeros(L,1)
length(L)
als maximale Tiefefor idx(depth) = 1:L(depth)
length(L)
, führen Sie die Elementoperation aus, andernfalls rufen Sie die Funktion erneut mit aufdepth+1
Nicht so schnell wie vektorisierte Methoden, wenn Sie alle Punkte überprüfen möchten, aber wenn Sie die meisten nicht bewerten müssen, kann dies eine ziemliche Zeitersparnis bedeuten.
quelle
Diese Lösungen sind schneller (ca. 11%) als die Verwendung
numel
;)oder
UPD. tnx @rayryeng für erkannten Fehler in der letzten Antwort
Haftungsausschluss
Die Timing-Informationen, auf die in diesem Beitrag verwiesen wird, sind aufgrund eines grundlegenden Tippfehlers falsch und ungenau (siehe Kommentar-Stream unten sowie den Bearbeitungsverlauf - siehe insbesondere die erste Version dieser Antwort). Vorbehalt Emptor .
quelle
1 : array(:)
ist äquivalent zu1 : array(1)
. Dies durchläuft nicht alle Elemente, weshalb Ihre Laufzeiten schnell sind. Darüber hinaus werden Gleitkommazahlenrand
generiert , und dies würde ein leeres Array erzeugen, wenn Ihre Anweisung versucht, einen ansteigenden Vektor mit dem Anfangswert 1 mit einem Endwert als Gleitkommazahl mit einem Bereich von ausschließlich 1 zu finden Schritte von 1. Es gibt keinen solchen möglichen Vektor, was zu einem leeren Vektor führt. Ihre Schleife wird nicht ausgeführt, daher ist Ihre Behauptung falsch. -1 Stimme. Es tut uns leid.1 : array(:)
[0,1)
for
reshape(...)
.1 : array(:)
Ihrer Eingabeaufforderung nach dem Erstellenarray
. Erhalten Sie eine leere Matrix? Wenn ja, funktioniert Ihr Code nicht. Ich verlasse meine Stimme, weil Sie falsche Angaben machen.Wenn Sie sich die anderen Verwendungszwecke
size
genauer ansehen, können Sie feststellen, dass Sie tatsächlich einen Vektor mit der Größe jeder Dimension erhalten können. Dieser Link zeigt Ihnen die Dokumentation:www.mathworks.com/access/helpdesk/help/techdoc/ref/size.html
Nachdem Sie den Größenvektor erhalten haben, iterieren Sie über diesen Vektor. So etwas (entschuldigen Sie meine Syntax, da ich Matlab seit dem College nicht mehr verwendet habe):
Machen Sie dies zu einer tatsächlichen Matlab-legalen Syntax, und ich denke, es würde tun, was Sie wollen.
Außerdem sollten Sie in der Lage sein, die hier beschriebene lineare Indizierung durchzuführen .
quelle
Sie möchten n-verschachtelte for-Schleifen simulieren.
Das Iterieren durch ein n-dimensionales Array kann als Erhöhen der n-stelligen Zahl angesehen werden.
Bei jeder Dimension haben wir so viele Ziffern wie die Länge der Dimension.
Beispiel:
Angenommen, wir hätten ein Array (Matrix)
in "zur Notation" haben wir:
Um dies zu simulieren, müssten Sie die "n-stellige Notation" verwenden.
Wir haben eine 3-stellige Nummer mit 3 Ziffern für die erste, 4 für die zweite und fünf für die dritte Ziffer
Wir müssen die Anzahl erhöhen, damit wir die Sequenz erhalten
Sie können also den Code zum Erhöhen dieser n-stelligen Zahl schreiben. Sie können dies so tun, dass Sie mit einem beliebigen Wert der Zahl beginnen und die Ziffern um eine beliebige Zahl erhöhen / verringern können. Auf diese Weise können Sie verschachtelte Schleifen simulieren, die irgendwo in der Tabelle beginnen und nicht am Ende enden.
Dies ist jedoch keine leichte Aufgabe. Ich kann leider nicht mit der Matlab-Notation helfen.
quelle