Чи є передбачення в MATLAB? Якщо так, то як він поводиться, якщо основні дані змінюються?


170

Чи існує структура передбачень у MATLAB? Якщо так, що станеться, якщо основні дані змінюються (тобто якщо об'єкти додаються до набору)?

Відповіді:


146

Петля FOR MATLAB має статичний характер; ви не можете змінювати змінну циклу між ітераціями, на відміну від структури циклу for (ініціалізація; умова; збільшення) в інших мовах. Це означає, що наступний код завжди друкує 1, 2, 3, 4, 5 незалежно від значення B.

A = 1:5;

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

Якщо ви хочете відповісти на зміни в структурі даних під час ітерацій, цикл WHILE може бути більш підходящим --- ви зможете протестувати стан циклу при кожній ітерації та встановити значення змінної циклу ( s) за бажанням:

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

Btw, цикл для кожного в Java (і, можливо, інших мовах) виробляє не визначене поведінку, коли структура даних змінюється під час ітерації. Якщо вам потрібно змінити структуру даних, ви повинні використовувати відповідний екземпляр Iterator, який дозволяє додавати та вилучати елементи в колекцію, яку ви ітератуєте. Хороша новина полягає в тому, що MATLAB підтримує об’єкти Java, тому ви можете зробити щось подібне:

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 не визначено, ваш перший приклад не надрукує 1-5. Це друкує Undefined function or variable 'B'.
Клейст

3
Для першого прикладу переконайтеся, що Aце вектор рядка, а не вектор стовпця. Якщо Aматриця, кожен k буде вектором стовпця з цієї матриці. Отже, перенесіть ( A') або векторизуйте ( A(:)') за потреби.
юк

3
-1 Я не думаю, що подібний до Java код повинен бути вашим першим вибором для роботи з Matlab у .mфайлах.
bobobobo

1
привітання з майбутнього; ми підходимо до безлічі рішень проблеми інвалідації ітератора.
Дмитро

89

Зак правильний щодо прямої відповіді на запитання.

Цікавою стороною зауваження є те, що наступні дві петлі не виконуються однаково:

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

Перший цикл створює змінну, iяка є скалярною, і повторює її як C для циклу. Зауважте, що якщо ви модифікуєте iтіло циклу, змінене значення буде ігноруватися, як каже Зак. У другому випадку Matlab створює 10k-елементний масив, після чого він обходить усі елементи масиву.

Що це означає, що це

for i=1:inf
  % do something
end

працює, але

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

ні (тому що для цього потрібно було б виділити нескінченну пам'ять). Детальніше дивіться у блозі Лорен .

Також зауважте, що ви можете перебирати масиви клітин.


2
Так, я здивувався цьому, коли наткнувся на це. Ця оптимізація масивів фактично відбувається у багатьох місцях. Якщо ви використовуєте нотацію дужок, іноді ви побачите попередження про ефективність у редакторі Matlab, які говорять вам про те, що він може оптимізувати розподіл масиву, якщо ви дозволите це.
Містер Фооз

Я чую, що Матлаб зараз ледаче оцінює. Якщо ні, у нас є технологія їх впровадження.
Дмитро

19

MATLAB для циклу в основному забезпечує величезну гнучкість, включаючифункціональність. Ось кілька прикладів:

1) Визначте початок, приріст та кінець індексу

for test = 1:3:9
   test
end

2) Петля над вектором

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

3) Петля над рядком

for test = 'hello'
   test
end

4) Переведіть петлю на одновимірний масив комірок

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

5) Переведіть петлю на двовимірний масив комірок

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

6) Використовуйте назви структурних масивів

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

4
За допомогою масиву комірок врахуйте, що він повторюватиме стовпці масиву комірок.
Євгеній Сергєєв

17

Якщо ви намагаєтеся перевести цикл на масив комірок і застосувати щось до кожного елемента в комірці, перевірте cellfun. Є також arrayfun, bsxfunі structfunщо може спростити вашу програму.


хоча, з досвіду, я б сказав, що їхня ефективність дорівнює чи найгірша написанню циклу for-loop, але краще виглядає, і хто знає, що це може покращитися в майбутньому.

14

ооо! акуратне питання.

Matlab's для циклу приймає матрицю як вхідний і повторює свої стовпці. Matlab також обробляє практично все за значенням (без передачі посилань), тому я би сподівався, що він зробить знімок введення для циклу, щоб він був непорушним.

ось приклад, який може допомогти проілюструвати:

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

Під час ітерації над масивами комірок рядків змінна циклу (назвемо її так f) стає одноелементним масивом комірок. Необхідність писати f{1}всюди стає втомливою, а зміна змінної циклу забезпечує чітке вирішення.

% 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

Скажімо, у вас є масив даних:

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

тоді ви можете "передбачити" це так:

for i = n, i, end

Це повторить кожен елемент у n (але, звичайно, можлива також заміна i на більш цікаві речі!)


4

Я думаю, що цього дійсно хоче ОП:

array = -1:0.1:10

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

Це просто виводить 10, оскільки numel(array)це кількість елементів у масиві. можливо, ти мав на увазі 1:numel(array)?
Клейст

Не for i = -1:0.1:10; disp(i); end;було б краще?
Оріол

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.