Есть ли в MATLAB foreach? Если да, то как он себя ведет, если базовые данные изменяются?


171

Есть ли в MATLAB структура foreach? Если так, что произойдет, если базовые данные изменятся (то есть, если объекты будут добавлены в набор)?

Ответы:


147

Цикл 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)])

Кстати, цикл for-each в 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 будет вектором столбца из этой матрицы. Таким образом, transpose ( A') или vectorize ( A(:)') при необходимости.
ЮК

3
-1 Я не думаю, что Java-подобный код должен быть вашим первым выбором для работы с Matlab в .mфайлах.
Бобобобо

1
привет из будущего; у нас есть множество решений проблемы аннулирования итераторов.
Дмитрий

90

Зак прав насчет прямого ответа на вопрос.

Интересно отметить, что следующие два цикла не выполняются одинаково:

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

Первый цикл создает переменную, iкоторая является скаляром, и повторяет ее как цикл C for. Обратите внимание, что если вы изменяете iв теле цикла, измененное значение будет игнорироваться, как говорит Зак. Во втором случае Matlab создает массив из 10 тыс. Элементов, а затем обходит все элементы массива.

Это значит, что

for i=1:inf
  % do something
end

работает, но

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

нет (потому что это потребовало бы выделения бесконечной памяти). Смотрите блог Лорен для деталей.

Также обратите внимание, что вы можете перебирать массивы ячеек.


2
Да, я был удивлен этим, когда столкнулся с этим. Эта оптимизация массивов на самом деле происходит во многих местах. Если вы используете скобочные обозначения, иногда вы увидите предупреждения о производительности в редакторе Matlab, говорящие вам, что он может оптимизировать распределение массива, если вы позволите.
Мистер Фуз

Я слышал, у Матлаба сейчас ленивая оценка. Если нет, у нас есть технологии для их реализации.
Дмитрий

19

MATLAB for loop в основном обеспечивает огромную гибкость, включаяфункциональность. Вот несколько примеров:

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, хотя лучше выглядит, и кто знает, что они могут улучшиться в будущем.

14

ооо! аккуратный вопрос.

Цикл for Matlab принимает матрицу в качестве входных данных и перебирает ее столбцы. Matlab также обрабатывает практически все по значению (без передачи по ссылке), поэтому я ожидаю, что он сделает снимок ввода цикла for, чтобы он был неизменным.

Вот пример, который может помочь проиллюстрировать:

>> 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;будет лучше?
Oriol

4

На сегодняшний день (27 февраля) в MATLAB File Exchange появился новый набор инструментов For-Each, который реализует концепцию foreach. foreachне является частью языка MATLAB, но использование этого набора инструментов дает нам возможность подражать тому, что foreachбудет делать.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.