Операторы итерации — for , foreach , do и while
Операторы итерации многократно выполняют инструкцию или блок инструкций. Оператор for выполняет текст, пока указанное логическое выражение вычисляется true . Инструкция foreach перечисляет элементы коллекции и выполняет его текст для каждого элемента коллекции. Оператор do условно выполняет свой текст один или несколько раз. Оператор while условно выполняет его тело ноль или более раз.
В любой момент в тексте инструкции итерации можно выйти из цикла с помощью инструкции break . Вы можете перейти к следующей итерации в цикле с помощью инструкции continue .
Инструкция for
Оператор for выполняет оператор или блок операторов, пока определенное логическое выражение равно значению true . В следующем примере показана инструкция for , выполняющая тело пока целочисленный счетчик меньше трех:
for (int i = 0; i < 3; i++) < Console.Write(i); >// Output: // 012
В предыдущем примере показаны элементы оператора for :
-
Раздел инициализатора, который выполняется только один раз перед входом в цикл. Как правило, в этом разделе объявляется и инициализируется локальная переменная цикла. Доступ к объявленной переменной извне оператора for невозможен. В разделе инициализатора в предыдущем примере объявляется и инициализируется целочисленная переменная-счетчик:
int i = 0
Раздел итератора может содержать ноль или более следующих выражений оператора, разделенных запятыми:
- префиксное или постфиксное выражение приращения, такое как ++i или i++
- префиксное или постфиксное выражение декремента, такое как —i или i—
- присваивание
- вызов метода
- Выражение await
- создание объекта с помощью new оператора
Если переменная цикла не объявлена в разделе инициализатора, в разделе инициализатора можно также использовать ноль или более выражений из предыдущего списка. В следующем примере показано несколько менее распространенных вариантов использования разделов инициализатора и итератора: присваивание значения внешней переменной цикла в разделе инициализатора, вызов метода в разделах инициализатора и итератора и изменение значения двух переменных в разделе итератора.
int i; int j = 3; for (i = 0, Console.WriteLine($"Start: i=, j="); i < j; i++, j--, Console.WriteLine($"Step: i=, j=")) < //. >// Output: // Start: i=0, j=3 // Step: i=1, j=2 // Step: i=2, j=1
Все разделы оператора for необязательны. Например, в следующем коде определяется бесконечный цикл for :
Инструкция foreach
Оператор foreach выполняет оператор или блок операторов для каждого элемента в экземпляре типа, который реализует интерфейс System.Collections.IEnumerable или System.Collections.Generic.IEnumerable , как показано в следующем примере.
List fibNumbers = [0, 1, 1, 2, 3, 5, 8, 13]; foreach (int element in fibNumbers) < Console.Write($""); > // Output: // 0 1 1 2 3 5 8 13
Оператор foreach не ограничен этими типами. Его можно использовать с экземпляром любого типа, который удовлетворяет следующим условиям:
- Тип имеет открытый метод без параметров GetEnumerator . Этот GetEnumerator метод может быть методом расширения типа.
- тип возвращаемого значения метода GetEnumerator должен содержать открытое свойство Current и открытый метод MoveNext без параметров с типом возвращаемого значения bool .
В следующем примере показано использование оператора foreach с экземпляром типа System.Span , который не реализует интерфейс:
Span numbers = [3, 14, 15, 92, 6]; foreach (int number in numbers) < Console.Write($""); > // Output: // 3 14 15 92 6
Если свойство перечислителя Current возвращает возвращаемое значение ссылки ( ref T где T тип элемента коллекции), можно объявить переменную итерации с ref ref readonly модификатором, как показано в следующем примере:
Span storage = stackalloc int[10]; int num = 0; foreach (ref int item in storage) < item = num++; >foreach (ref readonly var item in storage) < Console.Write($""); > // Output: // 0 1 2 3 4 5 6 7 8 9
Если исходная коллекция инструкции foreach пуста, тело оператора foreach не выполняется и пропускается. Если оператор foreach применяется к null , возникает исключение NullReferenceException.
await foreach
await foreach (var item in GenerateSequenceAsync())
Оператор await foreach можно также использовать с экземпляром любого типа, который удовлетворяет следующим условиям:
- Тип имеет открытый метод без параметров GetAsyncEnumerator . Этот метод может быть методом расширения типа.
- Тип возвращаемого значения метода GetAsyncEnumerator имеет открытое свойство Current и открытый метод без параметров MoveNextAsync , тип возвращаемого значения которого — Task , ValueTask или любой другой подтверждающий ожидание тип, метод ожидания которого GetResult возвращает значение bool .
Элементы потока по умолчанию обрабатываются в захваченном контексте. Чтобы отключить захват контекста, используйте метод расширения TaskAsyncEnumerableExtensions.ConfigureAwait. Дополнительные сведения о контекстах синхронизации и захвате текущего контекста см. в статье Использование асинхронного шаблона, основанного на задачах. Дополнительные сведения об асинхронных потоках см. в руководстве по асинхронным потокам.
Тип переменной итерации
Можно использовать ключевое слово var , чтобы компилятор мог определить тип переменной итерации в операторе foreach , как показано в следующем коде:
foreach (var item in collection)
var Тип может быть выведен компилятором в качестве ссылочного типа, допускающего значение NULL, в зависимости от того, включен ли контекст с поддержкой NULL и является ли тип выражения инициализации ссылочным типом. Дополнительные сведения см . в разделе неявно типизированные локальные переменные.
Можно также явно указать тип переменной итерации, как показано в следующем коде:
IEnumerable collection = new T[5]; foreach (V item in collection)
В предыдущей форме тип T элемента коллекции должен быть неявно или явно преобразован в тип V переменной итерации. Если явное преобразование из T в V завершается ошибкой во время выполнения, оператор foreach выдает исключение InvalidCastException. Например, если T является незапечатанным типом класса, V может быть любым типом интерфейса, даже тем, который T не реализует. Во время выполнения тип элемента коллекции может быть производным от T и фактически реализовать V . В противном случае возникает InvalidCastException.
Инструкция do
Оператор do выполняет оператор или блок операторов, пока определенное логическое выражение равно значению true . Так как это выражение оценивается после каждого выполнения цикла, цикл do выполняется один или несколько раз. Цикл do отличается от while цикла, который выполняется нулевым или более раз.
В следующем примере показано применение оператора do .
int n = 0; do < Console.Write(n); n++; >while (n < 5); // Output: // 01234
Инструкция while
Оператор while выполняет оператор или блок операторов, пока определенное логическое выражение равно значению true . Так как это выражение оценивается перед каждым выполнением цикла, цикл while выполняется ноль или несколько раз. Цикл while отличается от do цикла, который выполняется один или несколько раз.
В следующем примере показано применение оператора while .
int n = 0; while (n < 5) < Console.Write(n); n++; >// Output: // 01234
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
Дополнительные сведения об этих функциях см. в следующих заметках о предложении функций:
- Асинхронные потоки
- Поддержка расширения GetEnumerator для циклов foreach
См. также
Совместная работа с нами на GitHub
Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.
Прервать цикл forEach (javascript)
Есть массив со значениями. Внутри цикла есть условие поиска значения массива. Задача: остановить дальнейший перебор цикла при первом найденном значении. Спасибо за помощь. Решение: (спасибо Lieutenant Jim Dangle)
[1, 2, 3, 4, 3].some(function(el,i) < if (el == 3) < console.log(i); return el; >>);
Отслеживать
Менеджер Типографии
задан 6 янв 2017 в 12:28
Менеджер Типографии Менеджер Типографии
587 2 2 золотых знака 5 5 серебряных знаков 18 18 бронзовых знаков
@LieutenantJimDangle, твой код так же не работает как и код в вопросе 🙂
6 янв 2017 в 12:40
@LieutenantJimDangle, это просто убирает синтаксическую ошибку
6 янв 2017 в 12:43
Добавь в вопрос пример твоего массива, и что именно в нем ты хочешь найти и вывести.
6 янв 2017 в 12:59
Код решения неверен. результат возвращаемый функцией Callback переданной в some нужен только для проверки останавливать ли проход по коллекции или нет. Поэтому если вдруг искомый элемент будет 0 - то в твоем случае some пройдет по всей коллекции
6 янв 2017 в 13:09
4 ответа 4
Сортировка: Сброс на вариант по умолчанию
метод forEach не предусматривает возможности прервать обход коллекции.
Если нужно проверить наличие конкретного элемента удовлетворяющего условию, лучше использовать метод some
var massiv = ['2', '1', '3']; console.log(massiv.some(function(item) < console.log('some', item); return (item == "1"); >));
Если проверяются полностью объекты, можно использовать метод indexOf
var massiv = ['2', '1', '3']; console.log(massiv.indexOf("1"));
Если нужно найти индекс элемента удовлетворяющего условию, то подойдет метод findIndex
var massiv = ['2', '1', '3']; console.log(massiv.findIndex(function(item) < console.log('findIndex', item); return item == "1"; >));
Если очень хочется использовать именно forEach - можно поместить его в try..catch и кидать ошибку если элемент найден.
var massiv = ['2', '1', '3']; try < massiv.forEach(function(item, i) < console.log('foreach', i); if (item == "1") < throw < reason: "finded", index: i >> >); > catch (< reason, index >) < if (reason) < console.log(reason, ':', index) >>
Вместо встроенных функций массива, можно также воспользоваться циклом for . В этом случае для прерывания цикла можно использовать выражение break
Отслеживать
ответ дан 6 янв 2017 в 12:48
81k 9 9 золотых знаков 78 78 серебряных знаков 135 135 бронзовых знаков
Во всех варианта у Вас именно поиск конкретного элемента. А задача была найти первый найденный. В Вашей интерпритации массива было бы так: var massiv = ['2', '1', '3', '1']; И нужно найти индекс первой найденной еденички (то есть результатом остановки было бы значение 1 (второй элемент массива)
6 янв 2017 в 12:54
@МенеджерТипографии, все методы some , findIndex - прекращают выполнение, как только callback вернет true . Метод indexOf , находит первое вхождение элемента. начиная с указанного индекса, так как индекс не указан, проверка начинается с первого элемента массива.
6 янв 2017 в 12:56
@МенеджерТипографии, если задача заключается просто в проверке наличия элементов в массиве. то foreach вообще не нужен. В противном случае, все методы делают то же самое что и код в вопросе, за исключением прекращения выполнения когда условие выполнилось
6 янв 2017 в 12:58
В методе forEach не предусмотренa остановка как в лупе посредством брейк.
Использовать every заместо forEach . Когда будет false , все остановится.
Это самый правильный способ.
massiv.every(function(item, i) < if (item == "1") < console.log(i); return false; >else < return true; >>);
Отслеживать
81k 9 9 золотых знаков 78 78 серебряных знаков 135 135 бронзовых знаков
ответ дан 6 янв 2017 в 12:32
3,416 1 1 золотой знак 10 10 серебряных знаков 18 18 бронзовых знаков
на счет Это самый правильный способ - можно поспорить
6 янв 2017 в 13:04
я привел пример точно на поставленый вопрос, это делает то, что надо @Менеджер Типографии, все остальные ответы, по моему мнению не еффктивны. есть четко поставленый вопрос, и есть решение.
6 янв 2017 в 13:23
some - делает абсолютно то же самое. разница только в знаке сравнения. И все это менее эффективно чем обычный for за счет постоянного вызова функции-коллбэка. Кроме того, неизвестно что вообще нужно автору, что именно он хочет делать с полученным элементом. нужен ли ему элемент или индекс элемента и т.д.
Как можно выйти из цикла foreach js
В JavaScript цикл forEach не имеет стандартного способа выйти из него до его завершения. Как уже упоминалось, оператор break не работает в цикле forEach . Однако, можно использовать исключения (throw) для выхода из цикла.
Пример кода, который использует исключения для выхода из цикла forEach :
const array = [1, 2, 3, 4, 5]; let isValueFound = false; try array.forEach(function (element) if (element === 3) isValueFound = true; throw new Error('Value found'); > >); > catch (e) if (e.message !== 'Value found') throw e; > > if (isValueFound) console.log('Value is found'); > else console.log('Value is not found'); >
Однако, использование исключений может сделать код менее читаемым и более сложным в отладке, поэтому использование исключений для управления потоком программы следует ограничивать только крайними случаями.
Цикл foreach и инструкции break/continue в PHP
Без цикла foreach не обходится ни один сайт. Разберёмся как его использовать и можно ли прерывать или пропускать итерации цикла.
Цикл foreach
Цикл foreach - это лучший помощник программиста сайтов. Его можно встретить практически в любом коде сайта. А выполняет он очень полезную функцию: обходит массив по элементам. Его синтаксис довольно простой, но потребуется время, чтобы вникнуть. Поэтому начнём с простейшего примера:
В результате выполнения такого кода, на экране появится следующее:
один два три
Разберём по порядку, что же произошло. Внутри скобок foreach написано $a as $b, что означает: "бери по порядку элементы массива $a и помещай их значение в $b". Что программа и делает: берёт первый элемент массива $a со значением 'один' и задаёт это значение переменной $b. А в теле цикла идёт вывод значения "echo $b;". Как только все команды из тела цикла выполнены, начинается вторая итерация: берётся второй элемент из массива $a со значением 'два'. Производится то же самое действие. И так далее, пока в массиве не останется элементов.
Давайте усложним задачу и представим, что у массива есть ключи и их тоже надо передавать. А чтобы было не скучно, сделаем ключи текстовыми:
'один', 'two' => 'два', 'three' => 'три' ); foreach( $a as $b => $с )< echo $b; echo ' = '; echo $c; echo '
'; > ?>
В результате выполнения такого кода, на экране появится следующее:
one = один two = два three = три
Как можно видеть из примера, цикл отличается выражением в скобках $a as $b => $с. Это выражение означает "бери по порядку элементы массива $a и помещай их значение в $с, а ключи элементов в переменную $b".
Обратите внимание, что если внутри цикла изменить значение переменных $b или $с, то значение переменной $a не поменяется.
Чтобы изменить значение элемента массива $a, можно использовать внутри цикла foreach конструкцию $a[$b] = 'новое_значение'. Тогда в массиве $a, в элементе с ключом $b, изменится значение на 'новое_значение'
Прерывание цикла (break)
Бывают случаи, когда надо прервать цикл, выйти из него не продолжая. В этом поможет инструкция break. Попробуем протестировать его:
В результате выполнения такого кода, на экране получится следующее:
один два
Слово 'три' не будет напечатано, потому что в коде перед ним сработает инструкция break и цикл завершится.
Следующая итерация цикла (continue)
Иногда нужно не завершать цикл, а перейти к следующей итерации, к следующему элементу. Для этого используется инструкция continue:
В результате выполнения такого кода, на экране получится следующее:
один три
На элементе со значением 'два' сработает инструкция continue и последующие команды не будут выполнены. А вместо этого цикл начнётся заново, взяв следующий элемент массива $a.
Инструкции break и continue работают не только в циклах foreach, но и в циклах while и for.
Обратите внимание, что инструкции break и continue воздействуют только на родительский цикл, в котором находятся. Если несколько циклов вложено один в другой, а инструкция стоит внутри второго, то она никак не повлияет на первый цикл.
Пример из реального проекта
Приведём пример цикла, который приближен к циклу из реального проекта. Этот цикл будет находиться на странице со списком новостей и будет выводить название новости и короткое описание. Сам цикл будет проходить внутри массива, который описывает всю страницу. Именно таким способом программируются современные сайты: в начале ".php" файла вы загружаете данные из базы данных и собираете их большой-большой массив, обрабатываете и подготавливаете для вывода. А во второй части файла вы выводите значение элементов массива вперемешку с HTML кодом, но ничего не считаете и не обращаетесь к базе:
'Название первой новости', 'text' => 'Текст первой новости', ); $arResult['items'][] = array( 'name' => 'Название второй новости', 'text' => 'Текст второй новости', ); ?> ?>
В результате вызова этой страницы, в окне браузера мы увидим:
Название первой новости Текст первой новости Название второй новости Текст второй новости