Có một foreach trong MATLAB? Nếu vậy, nó hoạt động như thế nào nếu dữ liệu cơ bản thay đổi?


170

Có một cấu trúc foreach trong MATLAB? Nếu vậy, điều gì xảy ra nếu dữ liệu cơ bản thay đổi (nghĩa là nếu các đối tượng được thêm vào tập hợp)?

Câu trả lời:


146

Vòng lặp FOR của MATLAB có tính chất tĩnh; bạn không thể sửa đổi biến vòng lặp giữa các lần lặp, không giống như cấu trúc vòng lặp for (khởi tạo; điều kiện; tăng) trong các ngôn ngữ khác. Điều này có nghĩa là đoạn mã sau luôn in 1, 2, 3, 4, 5 bất kể giá trị của B.

A = 1:5;

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

Nếu bạn muốn có thể đáp ứng các thay đổi trong cấu trúc dữ liệu trong các lần lặp, vòng lặp WHILE có thể phù hợp hơn --- bạn sẽ có thể kiểm tra điều kiện vòng lặp ở mỗi lần lặp và đặt giá trị của biến vòng lặp ( s) như bạn muốn:

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

Btw, vòng lặp for- every trong Java (và có thể các ngôn ngữ khác) tạo ra hành vi không xác định khi cấu trúc dữ liệu được sửa đổi trong quá trình lặp. Nếu bạn cần sửa đổi cấu trúc dữ liệu, bạn nên sử dụng một cá thể Iterator thích hợp cho phép bổ sung và loại bỏ các phần tử trong bộ sưu tập mà bạn đang lặp. Tin vui là MATLAB hỗ trợ các đối tượng Java, vì vậy bạn có thể làm một cái gì đó như thế này:

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
Nếu B không xác định, ví dụ đầu tiên của bạn không in 1-5. Nó in Undefined function or variable 'B'.
Kleist

3
Đối với ví dụ đầu tiên, hãy chắc chắn rằng đó Alà một vectơ hàng, không phải vectơ cột. Nếu Alà một ma trận, mỗi k sẽ là một vectơ cột từ ma trận đó. Vì vậy, transpose ( A') hoặc vectorize ( A(:)') nếu cần.
yuk

3
-1 Tôi không nghĩ mã giống Java nên là cách lựa chọn đầu tiên của bạn để làm việc với Matlab trong .mcác tệp.
bobobobo

1
lời chào từ tương lai; chúng tôi đi kèm với rất nhiều giải pháp cho vấn đề vô hiệu hóa vòng lặp.
Dmitry

89

Zach là chính xác về câu trả lời trực tiếp cho câu hỏi.

Một lưu ý phụ thú vị là hai vòng lặp sau không thực hiện giống nhau:

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

Vòng lặp đầu tiên tạo ra một biến ilà vô hướng và nó lặp lại giống như vòng lặp C for. Lưu ý rằng nếu bạn sửa đổi itrong thân vòng lặp, giá trị được sửa đổi sẽ bị bỏ qua, như Zach nói. Trong trường hợp thứ hai, Matlab tạo ra một mảng phần tử 10k, sau đó nó đi bộ tất cả các phần tử của mảng.

Điều này có nghĩa là

for i=1:inf
  % do something
end

hoạt động, nhưng

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

không (vì cái này sẽ yêu cầu phân bổ bộ nhớ vô hạn). Xem blog của Loren để biết chi tiết.

Cũng lưu ý rằng bạn có thể lặp qua các mảng ô.


2
Vâng, tôi đã rất ngạc nhiên về điều này khi tôi gặp phải nó. Việc tối ưu hóa mảng này thực sự diễn ra ở nhiều nơi. Nếu bạn sử dụng ký hiệu dấu ngoặc, đôi khi bạn sẽ thấy các cảnh báo hiệu suất trong trình soạn thảo Matlab cho bạn biết nó nghĩ rằng nó có thể tối ưu hóa việc phân bổ mảng nếu bạn cho phép.
Ông Fooz

Tôi nghe Matlab có đánh giá lười biếng bây giờ. Nếu không, chúng tôi có công nghệ để thực hiện chúng.
Dmitry

19

MATLAB cho vòng lặp về cơ bản cho phép sự linh hoạt rất lớn, bao gồm cảchức năng. Dưới đây là một số ví dụ:

1) Xác định chỉ số bắt đầu, tăng và kết thúc

for test = 1:3:9
   test
end

2) Vòng qua vector

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

3) Lặp lại chuỗi

for test = 'hello'
   test
end

4) Lặp lại một mảng ô một chiều

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

5) Lặp lại một mảng ô hai chiều

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

6) Sử dụng tên trường của mảng cấu trúc

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

4
Với mảng ô, hãy lưu ý rằng nó sẽ lặp qua các cột của mảng ô.
Evgeni Sergeev

17

Nếu bạn đang cố gắng lặp qua một mảng ô và áp dụng một cái gì đó cho từng thành phần trong ô, hãy kiểm tra cellfun. Cũng có arrayfun, bsxfunstructfuncó thể đơn giản hóa chương trình của bạn.


mặc dù, từ kinh nghiệm tôi sẽ nói rằng hiệu suất của họ bằng hoặc tệ nhất là viết một vòng lặp for, mặc dù nhìn tốt hơn và ai biết họ có thể cải thiện trong tương lai.

14

Ồ! câu hỏi gọn gàng.

Vòng lặp for của Matlab lấy một ma trận làm đầu vào và lặp qua các cột của nó. Matlab cũng xử lý thực tế mọi thứ theo giá trị (không có tham chiếu qua) vì vậy tôi hy vọng rằng nó sẽ có một ảnh chụp nhanh về đầu vào của vòng lặp để nó không thay đổi.

đây là một ví dụ có thể giúp minh họa:

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

Khi lặp qua các mảng ô của chuỗi, biến vòng lặp (hãy gọi nó f) trở thành một mảng ô một phần tử. Phải viết f{1}ở khắp mọi nơi trở nên tẻ nhạt và sửa đổi biến vòng lặp cung cấp một cách giải quyết rõ ràng.

% 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

Giả sử bạn có một mảng dữ liệu:

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

sau đó bạn có thể 'thuyết minh' nó như thế này:

for i = n, i, end

Điều này sẽ lặp lại mọi yếu tố trong n (nhưng thay thế i bằng những thứ thú vị hơn cũng có thể xảy ra!)


4

Tôi nghĩ rằng đây là những gì OP thực sự muốn:

array = -1:0.1:10

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

Đó chỉ là in 10 vì numel(array)số lượng phần tử trong mảng. có lẽ bạn có ý nghĩa 1:numel(array)?
Kleist

Sẽ không for i = -1:0.1:10; disp(i); end;tốt hơn sao?
Oriol

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.