Работа с массивами практически всегда подразумевает итерацию по его элементам. Самый простой способ выполнить ее — это циклы, которые мы изучим в этом уроке.
Как обходить массив
Для начала рассмотрим код:
<?php
$userNames = ['petya', 'vasya', 'evgeny'];
for ($i = 0; $i < count($userNames); $i++) {
print_r("{$userNames[$i]}\n");
}
// => petya
// => vasya
// => evgeny
https://repl.it/@hexlet/php-arrays-traversal-for-print
В этом коде создается массив из трех элементов — имен. Далее в цикле происходит обход массива и вывод на экран всех имен. При этом каждое имя оказывается на новой строке.
Рассмотрим этот этап подробнее. Когда мы обходим массив циклом for
, счетчик играет роль индекса в массиве. Он инициализируется нулем и увеличивается до count($userNames) - 1
, что соответствует индексу последнего элемента.
Интересно производится печать на экран. Элемент массива может участвовать в строковой интерполяции, поэтому мы можем сразу печатать и имя и перевод строки, используя конструкцию "{$userNames[$i]}\n"
.
А что, если нам нужно вывести значения в обратном порядке? Для этого есть два способа. Первый способ — идти в прямом порядке от нулевого индекса до последнего и каждый раз вычислять нужный индекс по такой формуле:
размер массива - 1 - текущее значение счетчика
Но есть и другой способ. Можно просто идти от верхней границы к нижней. В такой ситуации код меняется на следующий:
<?php
$userNames = ['petya', 'vasya', 'evgeny'];
for ($i = count($userNames) - 1; $i >= 0; $i--) {
print_r("{$userNames[$i]}\n");
}
При таком обходе проверка остановки должна быть именно на >=
, иначе будет пропущен элемент с индексом 0
.
Изменение
Сам цикл при изменении остается тем же самым, меняется только его тело. Предположим, что мы хотим нормализовать список электронных адресов. Допустим, в нормализацию адресов входит приведение их к нижнему регистру. Тогда код будет выглядеть так:
<?php
$emails = ['VASYA@gmAil.com', 'iGoR@yandex.RU', 'netiD@hot.CoM'];
print_r($emails);
// => Array
// => (
// => [0] => VASYA@gmAil.com
// => [1] => iGoR@yandex.RU
// => [2] => netiD@hot.CoM
// => )
for ($i = 0; $i < count($emails); $i++) {
# strtolower — это стандартная функция PHP
$emails[$i] = strtolower($emails[$i]);
}
print_r($emails);
// => Array
// => (
// => [0] => vasya@gmail.com
// => [1] => igor@yandex.ru
// => [2] => netid@hot.com
// => )
https://repl.it/@hexlet/php-arrays-traversal-for-update
Здесь ключевая строчка — это $emails[$i] = strtolower($emails[$i]);
. В ней происходит перезапись элемента под индексом $i
. Иногда полезно создать промежуточную переменную. Это упрощает анализ кода:
<?php
$email = $emails[$i];
$emails[$i] = strtolower($email);
Инициализация цикла
При инициализации цикла for
в круглых скобках располагаются три блока выражений, разделяемые символом ;
.
Содержимое первого блока инициализации выполняется перед началом цикла и только один раз.
Второй блок определяет условие выполнения цикла и содержит выражение, которое вычисляется перед каждой очередной итерацией. Работа цикла продолжается, если это выражение возвращает true
. Если же проверка оказывается ложной, цикл заканчивает свою работу.
В третьем блоке содержатся выражения, которые обрабатываются в конце итерации цикла. Обычно здесь происходит необходимое преобразование счетчика — например, инкремент:
<?php
$colors = ['red', 'black', 'white', 'green'];
for ($i = 0; $i < count($colors); $i++) {
print_r("{$colors[$i]}\n");
}
В процессе работы цикла мы заново вычисляем выражение, которое содержится в блоке условий. Это значит, что в нашем примере длина массива count($colors)
будет вычисляться вновь и вновь при каждом проходе цикла. Сам массив остается неизменным, поэтому повторное вычисление размера оказывается избыточным. Повторения операции можно избежать, если определить переменную за пределами цикла и присвоить ей необходимое значение:
<?php
$colors = ['red', 'black', 'white', 'green'];
$length = count($colors);
for ($i = 0; $i < $length; $i++) {
print_r("{$colors[$i]}\n");
}
Но существует более оптимальное решение: описать несколько выражений в блоке инициализации цикла for
и разделить их запятыми. Это позволяет избегать лишних вычислений. В нашем примере мы можем единожды определить значение length
. Также мы сразу увидим переменные, которые используются только внутри цикла:
<?php
$colors = ['red', 'black', 'white', 'green'];
for ($i = 0, $length = count($colors); $i < $length; print($i), $i++) {
print_r("{$colors[$i]}\n");
}
// => red
// => 0black
// => 1white
// => 2green
// => 3
https://repl.it/@hexlet/php-arrays-for-initialize
Еще рассмотрим пример использования нескольких выражений в блоке изменения счетчика:
<?php
for ($i = 0; $i < 5; print("$i\n"), $i++) {
// Some code
}
// => 0
// => 1
// => 2
// => 3
// => 4
https://repl.it/@hexlet/php-arrays-for-increment
Рассмотренные блоки могут быть пустыми, при этом в них сохранятся разделители ;
. Это допустимо, но так лучше не делать: в идеале все блоки должны быть полными и содержать понятное описание работы цикла.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.