Gibt es einen Foreach in MATLAB? Wenn ja, wie verhält es sich, wenn sich die zugrunde liegenden Daten ändern?

170

Gibt es eine foreach-Struktur in MATLAB? Wenn ja, was passiert, wenn sich die zugrunde liegenden Daten ändern (dh wenn Objekte zum Satz hinzugefügt werden)?

Pennen
quelle

Antworten:

146

Die FOR- Schleife von MATLAB ist statischer Natur. Sie können die Schleifenvariable zwischen Iterationen nicht ändern, im Gegensatz zur for- Struktur (Initialisierung; Bedingung; Inkrement) in anderen Sprachen. Dies bedeutet, dass der folgende Code unabhängig vom Wert von B immer 1, 2, 3, 4, 5 druckt.

A = 1:5;

for i = A
    A = B;
    disp(i);
end

Wenn Sie in der Lage sein möchten, während Iterationen auf Änderungen in der Datenstruktur zu reagieren, ist eine WHILE- Schleife möglicherweise besser geeignet. Sie können die Schleifenbedingung bei jeder Iteration testen und den Wert der Schleifenvariablen festlegen ( s) wie Sie möchten:

n = 10;
f = n;
while n > 1
    n = n-1;
    f = f*n;
end
disp(['n! = ' num2str(f)])

Übrigens erzeugt die for-each- Schleife in Java (und möglicherweise in anderen Sprachen) ein nicht angegebenes Verhalten, wenn die Datenstruktur während der Iteration geändert wird. Wenn Sie die Datenstruktur ändern müssen, sollten Sie eine geeignete Iterator- Instanz verwenden, mit der Elemente in der von Ihnen iterierten Sammlung hinzugefügt und entfernt werden können. Die gute Nachricht ist, dass MATLAB Java-Objekte unterstützt. Sie können also Folgendes tun:

A = java.util.ArrayList();
A.add(1);
A.add(2);
A.add(3);
A.add(4);
A.add(5);

itr = A.listIterator();

while itr.hasNext()

    k = itr.next();
    disp(k);

    % modify data structure while iterating
    itr.remove();
    itr.add(k);

end
Zach Scrivena
quelle
1
Wenn B undefiniert ist, druckt Ihr erstes Beispiel nicht 1-5. Es wird gedruckt Undefined function or variable 'B'.
Kleist
3
Stellen Sie für das erste Beispiel sicher, dass Aes sich um einen Zeilenvektor und nicht um einen Spaltenvektor handelt. Wenn Aes sich um eine Matrix handelt, ist jedes k ein Spaltenvektor aus dieser Matrix. Transponieren ( A') oder vektorisieren ( A(:)'), falls erforderlich.
Yuk
3
-1 Ich denke nicht, dass Java-ähnlicher Code Ihre erste Wahl sein sollte, um mit Matlab in .mDateien zu arbeiten.
Bobobobo
1
Grüße aus der Zukunft; Wir bieten zahlreiche Lösungen für das Problem der Iterator-Invalidierung.
Dmitry
89

Zach hat Recht mit der direkten Antwort auf die Frage.

Eine interessante Randnotiz ist, dass die folgenden zwei Schleifen nicht dasselbe ausführen:

for i=1:10000
  % do something
end
for i=[1:10000]
  % do something
end

Die erste Schleife erstellt eine Variable i, die ein Skalar ist, und iteriert sie wie eine C for-Schleife. Beachten Sie dies, wenn Sie Änderungen vornehmeni im Schleifenkörper der geänderte Wert ignoriert wird, wie Zach sagt. Im zweiten Fall erstellt Matlab ein Array mit 10k Elementen und durchläuft dann alle Elemente des Arrays.

Was dies bedeutet ist das

for i=1:inf
  % do something
end

funktioniert, aber

for i=[1:inf]
  % do something
end

nicht (weil dies die Zuweisung von unendlichem Speicher erfordern würde). Siehe Lorens Blog für Details.

Beachten Sie auch, dass Sie über Zellenarrays iterieren können.

Herr Fooz
quelle
2
Ja, ich war überrascht, als ich darauf stieß. Diese Optimierung von Arrays findet tatsächlich an vielen Orten statt. Wenn Sie die Klammernotation verwenden, werden im Matlab-Editor manchmal Leistungswarnungen angezeigt, die darauf hinweisen, dass die Array-Zuordnung optimiert werden kann, wenn Sie dies zulassen.
Herr Fooz
Ich habe gehört, Matlab hat jetzt eine faule Bewertung. Wenn nicht, haben wir die Technologie, um sie zu implementieren.
Dmitry
19

Die MATLAB for- Schleife ermöglicht grundsätzlich eine enorme Flexibilität, einschließlich derFunktionalität. Hier einige Beispiele:

1) Definieren Sie den Start-, Inkrement- und Endindex

for test = 1:3:9
   test
end

2) Schleife über Vektor

for test = [1, 3, 4]
   test
end

3) Schleife über String

for test = 'hello'
   test
end

4) Schleife über ein eindimensionales Zellenarray

for test = {'hello', 42, datestr(now) ,1:3}
   test
end

5) Schleife über ein zweidimensionales Zellenarray

for test = {'hello',42,datestr(now) ; 'world',43,datestr(now+1)}
   test(1)   
   test(2)
   disp('---')
end

6) Verwenden Sie Feldnamen von Strukturarrays

s.a = 1:3 ; s.b = 10  ; 
for test = fieldnames(s)'
   s.(cell2mat(test))
end
BHF
quelle
4
Beachten Sie beim Zellenarray, dass es über Spalten des Zellenarrays iteriert .
Evgeni Sergeev
17

Wenn Sie versuchen, ein Zellenarray zu durchlaufen und auf jedes Element in der Zelle etwas anzuwenden, überprüfen Sie dies cellfun. Es gibt auch arrayfun, bsxfunund structfundas kann Ihr Programm vereinfachen.

Loren
quelle
Aus Erfahrung würde ich jedoch sagen, dass ihre Leistung dem Schreiben einer For-Schleife entspricht oder am schlechtesten ist, aber besser aussieht und wer weiß, dass sie sich in Zukunft verbessern könnten.
14

Oh! nette Frage.

Die for-Schleife von Matlab verwendet eine Matrix als Eingabe und iteriert über ihre Spalten. Matlab behandelt praktisch alles nach Wert (keine Referenzübergabe), sodass ich erwarten würde, dass es eine Momentaufnahme der Eingabe der for-Schleife macht, damit sie unveränderlich ist.

Hier ist ein Beispiel, das zur Veranschaulichung beitragen kann:

>> A = zeros(4); A(:) = 1:16

A =

     1     5     9    13
     2     6    10    14
     3     7    11    15
     4     8    12    16

>> i = 1; for col = A; disp(col'); A(:,i) = i; i = i + 1; end;
     1     2     3     4

     5     6     7     8

     9    10    11    12

    13    14    15    16

>> A

A =

     1     2     3     4
     1     2     3     4
     1     2     3     4
     1     2     3     4
Jason S.
quelle
7

Beim Durchlaufen von Zellenarrays von Zeichenfolgen wird die Schleifenvariable (nennen wir es f) zu einem Einzelelement-Zellenarray. f{1}Überall schreiben zu müssen wird mühsam, und das Ändern der Schleifenvariablen bietet eine saubere Problemumgehung.

% This example transposes each field of a struct.
s.a = 1:3;
s.b = zeros(2,3);
s % a: [1 2 3]; b: [2x3 double]
for f = fieldnames(s)'
    s.(f{1}) = s.(f{1})';
end
s % a: [3x1 double]; b: [3x2 double]

% Redefining f simplifies the indexing.
for f = fieldnames(s)'
    f = f{1};
    s.(f) = s.(f)';
end
s % back to a: [1 2 3]; b: [2x3 double]

quelle
5

Angenommen, Sie haben eine Reihe von Daten:

n = [1    2   3   4   6   12  18  51  69  81  ]

dann können Sie es so 'foreach':

for i = n, i, end

Dies wird jedes Element in n wiedergeben (aber das Ersetzen des i durch interessantere Dinge ist natürlich auch möglich!)

Skidder
quelle
4

Ich denke, das ist es, was das OP wirklich will:

array = -1:0.1:10

for i=1:numel(array)
    disp(array(i))
end
Geburt
quelle
Das gibt nur 10 aus, da dies numel(array)die Anzahl der Elemente im Array ist. vielleicht meintest du 1:numel(array)?
Kleist
Wäre nicht for i = -1:0.1:10; disp(i); end;besser?
Oriol