MATLAB'da bir foreach var mı? Eğer öyleyse, temeldeki veriler değişirse nasıl davranır?


171

MATLAB'da foreach yapısı var mı? Öyleyse, temel alınan veriler değişirse (yani, kümeye nesneler eklenirse) ne olur?

Yanıtlar:


147

MATLAB'ın FOR döngüsü doğada statiktir; diğer dillerdeki for (başlatma; koşul; artış) döngü yapısının aksine, yinelemeler arasındaki döngü değişkenini değiştiremezsiniz . Bu, aşağıdaki kodun B değerinden bağımsız olarak her zaman 1, 2, 3, 4, 5 yazdırdığı anlamına gelir.

A = 1:5;

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

Yinelemeler sırasında veri yapısındaki değişikliklere yanıt vermek istiyorsanız, bir WHILE döngüsü daha uygun olabilir --- döngü durumunu her yinelemede test edebilir ve döngü değişkeninin değerini ( s) istediğiniz gibi:

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

Btw, Java'daki (ve muhtemelen diğer dillerdeki) her biri için döngü , veri yapısı yineleme sırasında değiştirildiğinde, belirtilmemiş davranış üretir. Veri yapısını değiştirmeniz gerekiyorsa , yinelediğiniz koleksiyondaki öğelerin eklenmesine ve kaldırılmasına izin veren uygun bir Iterator örneği kullanmalısınız . İyi haber şu ki MATLAB Java nesnelerini destekliyor, böylece böyle bir şey yapabilirsiniz:

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

1
B tanımsızsa, ilk örneğiniz 1-5 yazdırmaz. Yazdırır Undefined function or variable 'B'.
Kleist

3
İlk örnek için Abunun sütun vektörü değil, bir satır vektörü olduğundan emin olun . Eğer Abir matris, her bir k, bu matrisin bir sütun vektördür olacaktır. Bu nedenle, gerekirse transpoze edin ( A') veya vectorize edin ( A(:)').
yuk

3
-1 Ben do not düşünüyorum Java benzeri kod Matlab ile çalışmak için ilk tercih yolu olmalıdır .mdosyaları.
bobobobo

1
gelecekten selamlar; yineleyici geçersiz kılma sorununa birçok çözüm sunuyoruz.
Dmitry

90

Zach sorunun doğrudan cevabı konusunda haklı.

İlginç bir yan not, aşağıdaki iki döngünün aynı işlemi gerçekleştirmemesidir:

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

İlk döngü, iskaler olan bir değişken oluşturur ve bunu döngü için bir C gibi yineler. iDöngü gövdesinde değişiklik yaparsanız , Zach'in dediği gibi değiştirilen değerin yok sayılacağını unutmayın. İkinci durumda, Matlab 10k elemanlık bir dizi oluşturur, ardından dizinin tüm elemanlarını yürür.

Bunun anlamı şudur

for i=1:inf
  % do something
end

çalışır, ancak

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

(sonsuz bellek ayırmayı gerektireceğinden) bunu yapmaz. Ayrıntılar için Loren bloguna bakın.

Ayrıca hücre dizileri üzerinde yineleme yapabileceğinizi unutmayın.


2
Evet, onunla karşılaştığımda buna şaşırdım. Dizilerin bu optimizasyonu birçok yerde gerçekleşir. Köşeli ayraç gösterimi kullanırsanız, bazen Matlab düzenleyicisinde izin verirseniz dizi ayırmayı optimize edebileceğini düşündüğünü belirten performans uyarıları görürsünüz.
Bay Fooz

Matlab'ın tembel bir değerlendirme yaptığını duydum. Değilse, bunları uygulayacak teknolojimiz var.
Dmitry

19

Döngü için MATLAB temel olarak büyük esneklik sağlar,işlevsellik. İşte bazı örnekler:

1) Başlangıç, artış ve bitiş endeksini tanımlayın

for test = 1:3:9
   test
end

2) Vektör üzerinde döngü

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

3) Dize üzerinden döngü

for test = 'hello'
   test
end

4) Tek boyutlu bir hücre dizisi üzerinde döngü

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

5) İki boyutlu hücre dizisi üzerinde döngü

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

6) Yapı dizilerinin alan adlarını kullanma

s.a = 1:3 ; s.b = 10  ; 
for test = fieldnames(s)'
   s.(cell2mat(test))
end

4
Hücre dizisiyle, hücre dizisinin sütunları üzerinde yineleneceğini unutmayın .
Evgeni Sergeev

17

Bir hücre dizisi üzerinde döngü oluşturmaya ve hücredeki her öğeye bir şey uygulamayı deniyorsanız, bakın cellfun. Orada da var arrayfun, bsxfunve structfunprogramınızı basitleştirmek olabilir.


Yine de, deneyimlerden, performanslarının bir for-loop yazmaya eşit ya da kötü olduğunu, daha iyi baktığını ve gelecekte iyileşebileceklerini kimin bildiğini söyleyebilirim.

14

ooh! temiz soru.

Matlab for for loop, bir matrisi girdi olarak alır ve sütunları üzerinde tekrarlar. Matlab da pratik olarak her şeyi değerine göre (hiçbir pass-by-referans) işler, bu yüzden değişmez böylece for-loop girişinin bir anlık görüntüsünü alır beklenir.

İşte göstermeye yardımcı olabilecek bir örnek:

>> 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

7

Dizelerin hücre dizilerini yinelediğinde, döngü değişkeni (diyelim f) tek öğeli bir hücre dizisi haline gelir. Her yere yazmak f{1}zor oluyor ve döngü değişkenini değiştirmek temiz bir çözüm sağlıyor.

% 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]

5

Diyelim ki bir veri diziniz var:

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

o zaman bunu 'öngörebilirsiniz':

for i = n, i, end

Bu, n'deki her öğeyi tekrarlayacaktır (ancak i'yi daha ilginç şeylerle değiştirmek elbette mümkündür!)


4

Bence OP gerçekten bunu istiyor:

array = -1:0.1:10

for i=1:numel(array)
    disp(array(i))
end

Bu sadece 10 basar numel(array), çünkü dizideki eleman sayısıdır. belki demek istedin 1:numel(array)?
Kleist

Daha for i = -1:0.1:10; disp(i); end;iyi olmaz mıydı ?
Oriol

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.