Перейти к основному содержимому

Фильтрация коллекции

Фильтрация — это отбор тех элементов коллекции, которые удовлетворяют условию.

Условие записывают как функцию, которая принимает один элемент и возвращает true (оставить его) или false (пропустить). Такую функцию называют предикатом.

Фильтрация строит новый массив. Исходный массив не изменяется.

В PHP есть встроенный фильтр: array_filter(). Он принимает массив и предикат и возвращает новый массив с теми элементами, на которые предикат ответил «да». Короткий синтаксис стрелочной функции fn($w) => ... делает вызов компактным.

Важно помнить одно: array_filter() сохраняет исходные ключи. Когда нужен аккуратный список, снова пронумерованный с 0, оберните результат в array_values().


Фильтрация по предикату

Проще всего фильтровать, передав массив и предикат в array_filter(). По умолчанию предикат получает только значение.

С флагом ARRAY_FILTER_USE_BOTH предикат получает значение и ключ, так что ассоциативный массив можно фильтровать сразу по обоим. Флаг ARRAY_FILTER_USE_KEY передаёт только ключ.

В обычном списке ключи — это позиции 0, 1, 2, …, поэтому ARRAY_FILTER_USE_BOTH позволяет использовать в условии и индекс элемента.

Чтобы оставить элементы, которые не удовлетворяют условию, поставьте перед условием !. Отдельной функции filterNot в PHP нет.

Массив в PHP может хранить значения разных типов. is_string() проверяет, является ли значение строкой, а $v !== null пропускает записи, в которых нет значения.

Фильтрация массива

Оставляем только слова длиннее 3 букв. Условие strlen($w) > 3 передаётся в array_filter() как стрелочная функция.

array_filter() сохраняет исходные ключи, поэтому оставленные слова по-прежнему стоят под 2 и 3, и json_encode() выводит {"2":"three","3":"four"}. После array_values() ключи снова начинаются с 0, и тот же вызов выводит аккуратный список ["three","four"].

Prompt
Напишите PHP-скрипт, в котором слова one, two, three, four лежат в массиве. Оставьте слова длиннее 3 букв с помощью array_filter и стрелочной функции. Выведите отфильтрованный массив через json_encode, чтобы показать, что исходные ключи сохраняются, а затем выведите его ещё раз после того, как array_values перенумерует ключи.
Вывод: PHP-скрипт
Filter an array

Фильтрация ассоциативного массива

Остаются пары, ключ которых заканчивается на "1", а значение больше 10. Флаг ARRAY_FILTER_USE_BOTH заставляет array_filter() передавать предикату и значение, и ключ, а str_ends_with() проверяет конец ключа.

Prompt
Создайте ассоциативный массив, сопоставляющий ключам key1, key2, key3, key11 значения 1, 2, 3, 11. С помощью array_filter и флага ARRAY_FILTER_USE_BOTH оставьте только те пары, ключ которых заканчивается на «1», а значение больше 10. Выведите результат через json_encode.
Вывод: PHP-скрипт
Filter an associative array

Фильтрация с использованием индекса

В списке ключ каждого слова — это его позиция. С ARRAY_FILTER_USE_BOTH предикат видит слово и его индекс. Слово остаётся только если его индекс не 0 и в нём меньше 5 букв.

Prompt
Возьмите слова one, two, three, four. Используйте array_filter с ARRAY_FILTER_USE_BOTH, чтобы предикат получал ещё и позицию. Оставьте слово только если его позиция не 0 и оно короче 5 букв, затем переиндексируйте результат через array_values и выведите его с помощью json_encode.
Вывод: PHP-скрипт
Filter using the index

Фильтрация с инвертированным условием

Отбрасываем слова из 3 букв и меньше. Условие strlen($w) = 3 инвертируется с помощью !, поэтому остаются только более длинные слова.

Prompt
Возьмите слова one, two, three, four. Используйте array_filter, но инвертируйте условие с помощью !, чтобы слова длиной 3 буквы и меньше отбрасывались. Переиндексируйте результат через array_values и выведите его с помощью json_encode.
Вывод: PHP-скрипт
Filter with a negated condition

Фильтрация по типу

Массив содержит null, число, две строки и число с плавающей точкой. Обратный вызов is_string(...) — это сама встроенная функция, переданная с помощью синтаксиса first-class callable. Каждая оставленная строка выводится в верхнем регистре.

Prompt
Создайте массив, содержащий null, 1, "two", 3.5 и "four". С помощью array_filter и is_string(...) оставьте только строки. Выведите каждую оставленную строку в верхнем регистре, по одной на строку.
Вывод: PHP-скрипт
Filter by type

Отбрасывание значений null

Массив содержит строки и записи null. Явная проверка $v !== null оставляет настоящие значения. Не вызывайте здесь array_filter() без обратного вызова: он отбросил бы любое «ложное» значение, включая 0, "" и даже строку "0".

Prompt
Создайте массив, содержащий null, "one", null и "two". Оставьте значения, не равные null, с помощью array_filter и явной проверки !== null. Переиндексируйте результат через array_values и выведите его с помощью json_encode.
Вывод: PHP-скрипт
Filter out null values

Разделение

Иногда нужны обе группы: и элементы, которые удовлетворяют условию, и те, которые не удовлетворяют.

Встроенной операции partition в PHP нет. Её делает один цикл foreach: каждый элемент добавляется через []= либо в массив $match, либо в массив $rest. После цикла у вас есть оба массива.

Разделение массива на два

Слова длиннее 3 букв попадают в $match; все остальные — в $rest. Выводятся оба массива.

Prompt
Напишите PHP-скрипт, который одним циклом foreach разделяет слова one, two, three, four на два массива: слова длиннее 3 букв попадают в match, все остальные — в rest. Выведите оба массива через json_encode.
Вывод: PHP-скрипт
Split an array in two

Проверка предикатов

Иногда нужны не сами подходящие элементы, а только ответ «да» или «нет».

  • any: проходит ли проверку хотя бы один элемент? На это отвечает array_any(), новая функция в PHP 8.4, и она останавливается на первом совпадении.
  • none: не проходит ли проверку ни один элемент? Поставьте ! перед array_any().
  • all: проходит ли проверку каждый элемент? На это отвечает array_all(), тоже новая функция в PHP 8.4.

Без условия «есть ли хоть какой-нибудь элемент?» — это count($arr) > 0, а «нет ни одного элемента?» — это count($arr) === 0.

На пустом массиве array_all() возвращает true. Нет элемента, который не проходит проверку, поэтому проверка нигде не нарушена. Это называют тривиальной истиной.

Примеры выводят ответы с помощью json_encode(), который превращает логические значения в читаемый текст true и false.

any

Проверяем, заканчивается ли хотя бы одно слово на "e", а затем проверяем, есть ли в массиве хоть какой-нибудь элемент. array_any() останавливается, как только проверку проходит "one" — остальные слова не проверяются.

Prompt
Возьмите слова one, two, three, four. С помощью array_any проверьте, что хотя бы одно слово заканчивается на «e», и выведите ответ через json_encode. Затем выведите, есть ли в массиве хотя бы один элемент, проверив, что count больше 0.
Вывод: PHP-скрипт
any

none

Проверяем, что ни одно слово не заканчивается на "a", а затем проверяем, пуст ли массив. array_any() ничего не находит и возвращает false, поэтому ! превращает это в true.

Prompt
Возьмите слова one, two, three, four. С помощью ! и array_any проверьте, что ни одно слово не заканчивается на «a», и выведите ответ через json_encode. Затем выведите, пуст ли массив, проверив, что count равен 0.
Вывод: PHP-скрипт
none

all

Проверяем, заканчивается ли каждое слово на "e". array_all() останавливается на "two" и возвращает false. На пустом массиве она возвращает true.

Prompt
Возьмите слова one, two, three, four. С помощью array_all проверьте, что каждое слово заканчивается на «e», и выведите ответ через json_encode. Затем вызовите array_all на пустом массиве с тем же условием и выведите ответ.
Вывод: PHP-скрипт
all