Чат PHP-разработчиков
Цикл foreach: урок с практикой

Цикл foreach в PHP

Всем привет! В прошлом уроке мы с вами изучили основы массивов в PHP. Как вы уже поняли, массив может иметь довольно много элементов, и каждый из этих элементов, в свою очередь, также может являться массивом. Само собой, напрашивается вопрос: «А можно ли как-то автоматизировать обход по массиву?». То есть обращаться к его элементам по одному, не указывая при этом индексы значений. Ответ – можно. Для этого в PHP есть такая замечательная вещь, как циклы.

Давайте рассмотрим следующий пример:
Пусть по трассе едут 3 машины. Сделаем массив, в котором будут содержаться значения скоростей движения этих авто.

Код доступен только после покупки курса PHP для начинающих.

И допустим, нам нужно вычислить среднюю скорость движения этих автомобилей. Разумеется, зная, что автомобилей 3, мы могли бы сделать это с помощью выражения:

Код доступен только после покупки курса PHP для начинающих.

Простейшая школьная математика. Однако, если представить, что таких значений в массиве будет хотя бы 10, это уже приведёт к значительному разрастанию выражения. На помощь нам приходят циклы в PHP.

Рассмотрим в первую очередь языковую конструкцию foreach (от английского for – для, each - каждый). Она позволяет пройтись по каждому элементу массива. Она просто проходит по каждому элементу массива по очереди и позволяет выполнить с ним какое-либо действие.
Использование конструкции выглядит следующим образом:

Код доступен только после покупки курса PHP для начинающих.

где $array – это массив, $index и $value – это индекс и значение элемента на текущем шаге соответственно. Они на каждом новом элементе просто изменяют свои значения. Переменные $index и $value определяются прямо здесь, их раньше могло не существовать, они определяются прямо в процессе обхода массива.

То, что находится внутри фигурных скобок будет повторяться для каждого элемента массива. Один такой проход называется шагом или итерацией. Один элемент = одна итерация. Запомните это слово.
Цикл будет идти по массиву, пока не закончатся все элементы. Затем программа продолжит своё выполнение.

Давайте в качестве примера со скоростями обойдём массив и просто выведем индексы массива и его значения.

Код доступен только после покупки курса PHP для начинающих.

Результат:

Код доступен только после покупки курса PHP для начинающих.

Как мы видим, на первом шаге цикла в переменные $index и $speed попали значения 0 и 95 соответственно. На втором – 1 и 140 и так далее. Всё как мы и ожидали. Было выполнено 3 итерации.

Если нам не нужны индексы массива, то их можно не указывать в этой конструкции:

Код доступен только после покупки курса PHP для начинающих.

Такую конструкцию мы будем использовать, когда нам вообще нет дела до индексов и нужны только значения.

Вернёмся к задаче

Итак, нам нужно найти среднюю скорость. Для этого нам нужно:

  1. сложить все значения скоростей
  2. поделить получившуюся сумму на кол-во значений

Для того, чтобы выполнить первый шаг, давайте прибегнем к помощи цикла foreach:

Код доступен только после покупки курса PHP для начинающих.

Перед началом цикла определили переменную $sumOfSpeeds равную 0, а затем на каждой итерации прибавляли к ней значения скоростей. В конце просто вывели получившийся результат, который равен 313. Можете проверить на калькуляторе.

Теперь нужно разделить получившееся значение на число элементов.

Чтобы узнать число элементов в массиве можно прибегнуть к функции count($carSpeeds) – на вход передаётся имя массива. Полностью наш код будет выглядеть следующим образом:

Код доступен только после покупки курса PHP для начинающих.

На этом всё. Всем пока!

Домашнее задание
  • Придумайте способ обойтись без использования функции count.
Читайте также
Комментарии (40)


mahasamatman
<?php

$carsSpeeds = [
    95,
    140,
    78
];

$sumOfSpeeds = 0;
$countOfCars = 0;

foreach ($carsSpeeds as $speed) {
    $sumOfSpeeds += $speed;
    $countOfCars ++;
}

$averageSpeed = $sumOfSpeeds / $countOfCars;

echo 'Средняя скорость движения по трассе: ' . $averageSpeed;
ivashkevich

Всё правильно)

vasyaproject

А я не так делал, просто добавил $index и подсчитал его, это неправильно?

<?php 

$carWeight = [
    905,
    1200,
    1400
];

echo "Вес первой машины $carWeight[0] кг <br>
Вес второй машины $carWeight[1] кг <br>
Вес третьей машины $carWeight[2] кг <br>";

$sumCarWheight = 0;

foreach ($carWeight as $index => $wheight) {
    $sumCarWheight += $wheight;
    $sumCarIndex += $index;
}

echo 'Средний вес машин = ' . $sumCarWheight / $sumCarIndex . 'кг';

?>
vasyaproject

а нее, это неправильно :( уже сам увидел ошибку, если так, то оно просто складывает не порядковые index, а их числовые значения, надо тогда наверно так $sumCarIndex = $index + 1; или использовать такое $sumCarIndex = ++$index;

<?php 

$carWeight = [
    905,
    1200,
    1400
];

echo "Вес первой машины $carWeight[0] кг <br>
Вес второй машины $carWeight[1] кг <br>
Вес третьей машины $carWeight[2] кг <br>";

$sumCarWheight = 0;

foreach ($carWeight as $index => $wheight) {
    $sumCarWheight += $wheight;
    $sumCarIndex = $index + 1;
}

echo 'Средний вес машин = ' . $sumCarWheight / $sumCarIndex . 'кг';

?>
ivashkevich

Нет, неправильно. $sumCarIndex - сумма индексов, и она никак не соотносится с числом автомобилей, на которое нужно поделить сумму весов.
Вам просто повезло, что 0 + 1 + 2 = 3.
Если появится ещё один автомобиль то у вас уже будет 0 + 1 + 2 + 3 = 6.

trialex3
<?php
$carsSpeeds = [
    95,
    140,
    78,
    100,
    39
];
$sumOfSpeed = 0;
foreach ($carsSpeeds as $speed) {
    $sumOfSpeed += $speed;
}
$countOfCars = count($carsSpeeds);

$averageSpeed = $sumOfSpeed / $countOfCars;

echo 'Средняя скорость ' . $countOfCars . ' машин, ' . ' движущихся со скоростями ';
foreach ($carsSpeeds as $speed) {
    echo $speed . ', ';
}
echo 'равняется ' .'~' . (int)$averageSpeed;
?>
ivashkevich

Вы читали задание?

WarLikeLaux

enter image description here

ivashkevich

Непонятно, для чего вам здесь переменная $count, переменные $countOfCars и $sumOfSpeeds нужно определить перед циклом равными нулю. Иначе непонятно, что там за значения.

WarLikeLaux

Высчитывание среднего арифметического внутри функции, правда с использованием count
enter image description here

ivashkevich

Это бессмысленно - каждый раз проверять в цикле условие, которое выполнится лишь в конце. Нужно просто добавить счётчик перед циклом и увеличивать его внутри цикла. Попробуйте ещё раз.
Ах да, начинать нумерацию элементов массива с 1 тоже не надо.

serb2017
$carsSpeeds = [
    95,
    140,
    78
];

$sumOfSpeeds = 0;
foreach ($carsSpeeds as $index => $speed) {
        $sumOfSpeeds += $speed;
}
$averageSpeed = $sumOfSpeeds / ($index+1);

echo 'Средняя скорость движения по трассе без count: ' . $averageSpeed;
ivashkevich

Хорошо, но было бы лучше не полагаться на индексы массива, а сделать переменную $count = 0 перед циклом. И затем в каждой итерации увеличивать её на 1. Так будет более надежно. На случай, если какой-нибудь хулиган явно укажет значения индексов в исходном массиве =)

aseke465@gmail.com

Что неправильно? Найти средний бал семестра

<?php

$balls = [
    '1semestr' => [54,56,78,98,56,87],
    '2semestr' => [54,56,78,98,98],
    '3semestr' => ['1rubejka'=>[56,67,89], '2rubejka' => [76,78,98,90]],
];

?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title><?=$students['student1']?></title>
</head>
<body>
<h1><?
$sum_1sem =0;
$sum_2sem = 0;
$sum_3sem_1rub=0;
$sum_3sem_2rub = 0;
$sum_3sem = 0;
$sum_All=0;
foreach ($balls as $valueAll){
    foreach ($balls as $value_1sem){
        $sum_1sem+=$value_1sem;
        echo $sum_1sem/count($sum_1sem);
    }
    foreach ($balls as $value_2sem){
        $sum_2sem+=$value_2sem;
        echo $sum_1sem/count($sum_1sem);
    }
    foreach ($balls as $value_3sem){
        foreach ($balls as $value_1rub){
            $sum_3sem_1rub+=$value_1rub;
            echo $sum_3sem_1rub/count($sum_3sem_1rub);
        }
        foreach ($balls as $value_2rub){
            $sum_3sem_1rub+=$value_2rub;
            echo $sum_3sem_2rub/count($sum_3sem_2rub);
        }
        $sum_3sem+=$value_3sem;
        echo $sum_3sem/count($sum_3sem);
    }
    $sum_All+=$valueAll;
    echo $sum_All/count($sum_All);
}
?>
</body>
</html>
ivashkevich

А вы настройте отладчик и сами всё поймёте. Если не получится - подскажу.

SlipKnot

Домашка:

<?php
$carsSpeeds = [
    120,
    180,
    320
];
foreach ($carsSpeeds as $key => $cars)
{
    $count += $key;
    $speed += $cars;
}
echo 'Общее количество машин - ' . $count . '<br>';
echo 'Средняя скорость по трассе - ' . $speed / $count . ' км/ч<br>';
ivashkevich

Тут ошибка. Если в массив добавится ещё одна скорость, значение $count станет равным 6, а вам нужно получить число 4.

SlipKnot

Спасибо за ответ, сам бы не увидел и не догадался. Ну вот вроде исправил, добавил условие, если $keys >= 0, то прибавляем 1 в $count.

<?php
$carsSpeeds = [
    120,
    180,
    320,
    200,
    360
];
$count = 0;
foreach ($carsSpeeds as $key => $cars)
{
   if ($key >= 0) {
       $count += 1;
       $speed += $cars;
   }
}
echo 'Общее количество машин - ' . $count . '<br>';
echo 'Средняя скорость по трассе - ' . $speed / $count . ' км/ч<br>';
ivashkevich

А для чего вам это условие?

SlipKnot

Чтобы посчитать количество значений в массиве, только такая конструкция пришла на ум, и она работает) поправьте если не прав.

ivashkevich

А что будет, если убрать if, но оставить в цикле строки

       $count += 1;
       $speed += $cars;

Что-нибудь изменится?

Kirill123
$count = 0;
$resultOfSpeeds = 0;
$averageSpeeds = 0;

$carsSpeed = [
    95,
    140,
    78
];

foreach( $carsSpeed as $carSpeed ) {
    $count++;
    $resultOfSpeeds += $carSpeed;
}

$averageSpeeds = $resultOfSpeeds / $count;

echo $averageSpeeds;
Fox-24

Спс за урок!)

$carsSpeeds = [
    85,
    102,
    70
];

$sumOfSpeeds = 0;

$countOfCars = 0;
foreach ($carsSpeeds as $speed) {
    $sumOfSpeeds += $speed;
    $countOfCars = $countOfCars+1;
}

$averageSpeed = $sumOfSpeeds / $countOfCars;

echo 'Средняя скорость движения по трассе: ' . $averageSpeed;
ivashkevich

Отлично! Но вместо

$countOfCars = $countOfCars+1;

лучше

$countOfCars++;
Fox-24

Хорошо) Спасибо!

stasokulov@gmail.com
<?php
$carsSpeeds = [
    95,
    140,
    78
];

$sumOfSpeeds = 0;
$counter = 0;

foreach ($carsSpeeds as $speed) {
    $sumOfSpeeds += $speed;
    $counter++;
}

$averageSpeed = $sumOfSpeeds / $counter;

echo 'Средняя скорость движения по трассе: ' . $averageSpeed;
Benya
<?php

$carSpeeds = [
    95,
    140,
    78
];

$sumOfSpeed = 0;

foreach ($carSpeeds as $speed) {
    $sumOfSpeed +=$speed;
    $i++;

}
$averageSpeed = $sumOfSpeed / $i;

echo 'Средняя скорость движения по трасе:' . $averageSpeed;
ivashkevich

Отлично!

Bogdan

получается что если переменная создалась в цикле, то ее область виденья не ограничивается циклом?

ivashkevich

Нет. В PHP не ограничивается.

virtual2018
$sumOfSpeeds = 0;
$countOfCars = 0;

foreach ($carsSpeeds as $speed) {
    $sumOfSpeeds += $speed;
    $countOfCars++;
}

$averageSpeed = $sumOfSpeeds / $countOfCars;
Mike
<?php
$carSpeed = [
    90,
    87,
    115,
    56,
    170,
    10
];
$index=0;
$sumSpeed=0;
foreach ($carSpeed as $speed) {
   $index+=1;
   $sumSpeed+=$speed;

}
$averageSpeed = $sumSpeed / $index;
echo 'количество машин ' . $index . '<br>';
echo 'средняя скорость машин ' . $averageSpeed;
ivashkevich

Лучше назвать count а не index.

Bogdan
<?php

$score = 0;
$countOfCars = 0;
$carsSpeeds = [95, 140, 78];
foreach ($carsSpeeds as $index => $value) {
    $countOfCars += 1;
    $score += $carsSpeeds[$index];
}
echo $score / $countOfCars;

может конечно забегаю вперед, но а если цикл двумерный, как пройти по всем индексам? допустим я не знаю что цикл двумерный, и пошел командой foreach, а оно показало Array и все...

ivashkevich

Можно проверять текущее значение с помощью is_array. Если массив - запускать снова foreach. А еще можно сделать функцию рекурсивной - на вход принимает массив и перебирает все его элементы. Если элемент является массивом - вызывает себя же, передав в качестве аргумента этот элемент.

Популярное за сутки
Сейчас читают
Логические задачи с собеседований