Фильтрация коллекции
Фильтрация — это отбор тех элементов коллекции, которые удовлетворяют условию.
Условие записывают как функцию, которая принимает один элемент и возвращает 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"].
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four"];
// array_filter() оставляет каждый элемент, на который предикат ответил «да».
$longerThan3 = array_filter($words, fn($w) => strlen($w) > 3);
// Исходные ключи сохраняются: "three" и "four" остаются под ключами 2 и 3.
echo json_encode($longerThan3), "\n";
// array_values() перенумеровывает ключи с 0, давая аккуратный список.
echo json_encode(array_values($longerThan3)), "\n";
Фильтрация ассоциативного массива
Остаются пары, ключ которых заканчивается на "1", а значение больше 10. Флаг ARRAY_FILTER_USE_BOTH заставляет array_filter() передавать предикату и значение, и ключ, а str_ends_with() проверяет конец ключа.
Вывод: PHP-скрипт
<?php
$numbersMap = ["key1" => 1, "key2" => 2, "key3" => 3, "key11" => 11];
// ARRAY_FILTER_USE_BOTH передаёт предикату значение и ключ.
$filteredMap = array_filter(
$numbersMap,
fn($value, $key) => str_ends_with($key, "1") && $value > 10,
ARRAY_FILTER_USE_BOTH
);
echo json_encode($filteredMap), "\n";
Фильтрация с использованием индекса
В списке ключ каждого слова — это его позиция. С ARRAY_FILTER_USE_BOTH предикат видит слово и его индекс. Слово остаётся только если его индекс не 0 и в нём меньше 5 букв.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four"];
// В списке ключи — это позиции, поэтому ключ и есть индекс.
$filteredIdx = array_filter(
$words,
fn($w, $i) => $i !== 0 && strlen($w) < 5,
ARRAY_FILTER_USE_BOTH
);
echo json_encode(array_values($filteredIdx)), "\n";
Фильтрация с инвертированным условием
Отбрасываем слова из 3 букв и меньше. Условие strlen($w) = 3 инвертируется с помощью !, поэтому остаются только более длинные слова.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four"];
// В PHP нет filterNot: инвертируйте условие с помощью ! внутри предиката.
$filteredNot = array_filter($words, fn($w) => !(strlen($w) <= 3));
echo json_encode(array_values($filteredNot)), "\n";
Фильтрация по типу
Массив содержит null, число, две строки и число с плавающей точкой. Обратный вызов is_string(...) — это сама встроенная функция, переданная с помощью синтаксиса first-class callable. Каждая оставленная строка выводится в верхнем регистре.
Вывод: PHP-скрипт
<?php
$mixed = [null, 1, "two", 3.5, "four"];
// is_string(...) передаёт как предикат саму встроенную функцию.
$strings = array_filter($mixed, is_string(...));
foreach ($strings as $s) {
echo strtoupper($s), "\n";
}
Отбрасывание значений null
Массив содержит строки и записи null. Явная проверка $v !== null оставляет настоящие значения. Не вызывайте здесь array_filter() без обратного вызова: он отбросил бы любое «ложное» значение, включая 0, "" и даже строку "0".
Вывод: PHP-скрипт
<?php
$nullableList = [null, "one", null, "two"];
// Проверяйте на null сами: без обратного вызова array_filter() отбросил бы
// также любое другое «ложное» значение, например 0, "" и "0".
$values = array_filter($nullableList, fn($v) => $v !== null);
echo json_encode(array_values($values)), "\n";
Разделение
Иногда нужны обе группы: и элементы, которые удовлетворяют условию, и те, которые не удовлетворяют.
Встроенной операции partition в PHP нет. Её делает один цикл foreach: каждый элемент добавляется через []= либо в массив $match, либо в массив $rest. После цикла у вас есть оба массива.
Разделение массива на два
Слова длиннее 3 букв попадают в $match; все остальные — в $rest. Выводятся оба массива.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four"];
$match = [];
$rest = [];
foreach ($words as $w) {
if (strlen($w) > 3) {
$match[] = $w;
} else {
$rest[] = $w;
}
}
echo json_encode($match), "\n";
echo json_encode($rest), "\n";
Проверка предикатов
Иногда нужны не сами подходящие элементы, а только ответ «да» или «нет».
- 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" — остальные слова не проверяются.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four"];
// array_any() возвращает true, если проверку проходит хотя бы один элемент.
$anyE = array_any($words, fn($w) => str_ends_with($w, "e"));
echo json_encode($anyE), "\n";
// «есть ли хоть какой-нибудь элемент?» — это просто проверка количества.
echo json_encode(count($words) > 0), "\n";
none
Проверяем, что ни одно слово не заканчивается на "a", а затем проверяем, пуст ли массив. array_any() ничего не находит и возвращает false, поэтому ! превращает это в true.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four"];
// «none» — противоположность «any»: проверку не проходит ни один элемент.
$noneA = !array_any($words, fn($w) => str_ends_with($w, "a"));
echo json_encode($noneA), "\n";
// «нет ни одного элемента?» — это просто проверка количества.
echo json_encode(count($words) === 0), "\n";
all
Проверяем, заканчивается ли каждое слово на "e". array_all() останавливается на "two" и возвращает false. На пустом массиве она возвращает true.
Вывод: PHP-скрипт
<?php
$words = ["one", "two", "three", "four"];
// array_all() возвращает true только когда проверку проходит каждый элемент.
echo json_encode(array_all($words, fn($w) => str_ends_with($w, "e"))), "\n";
// В пустом массиве нет элемента, который не проходит проверку, поэтому array_all() возвращает true.
echo json_encode(array_all([], fn($w) => str_ends_with($w, "e"))), "\n";