Выборка данных из массива по диапазону значений: инструменты PHP

Раздел: PHP и структуры данных -> Работа с массивами

Основные подходы к фильтрации массива по диапазону значений

Эффективное решение: array_filter с анонимной функцией

Как быстро получить подмассив значений, попадающих в интервал от 10 до 20?


$numbers = [5, 12, 18, 25, 7, 14, 30];
$min = 10;
$max = 20;
$filtered = array_filter($numbers, function($value) use ($min, $max) {
    return $value >= $min && $value <= $max;
});

отсортировать массив по значению php (сортировка массива по значению php)

Функция array_filter проходит по каждому элементу и возвращает true, если элемент нужно оставить. Callback использует ключевое слово use для доступа к внешним переменным $min и $max. Результат: [12, 18, 14].

Типичная ошибка: не указать use, и переменные $min, $max будут не определены внутри callback. При использовании длинных массивов array_filter достаточно производителен, но при миллионах записей можно рассмотреть генераторы.

Классический цикл foreach

Как реализовать выборку без встроенных функций, чтобы лучше понимать логику?


$numbers = [5, 12, 18, 25, 7, 14, 30];
$min = 10; $max = 20;
$result = [];
foreach ($numbers as $value) {
    if ($value >= $min && $value <= $max) {
        $result[] = $value;
    }
}

цикл значений php (цикл по массиву в php)

Цикл добавляет подходящие значения в новый массив. Плюс: полный контроль над процессом, легко добавить дополнительные условия. Минус: больше кода, чем array_filter.

Проблема: если исходный массив имеет строковые ключи, они потеряются при добавлении через []. Для сохранения ключей нужно использовать $result[$key] = $value.

Использование array_reduce для функционального накопления

Как получить отфильтрованный массив с помощью свертки (reduce)?


$numbers = [5, 12, 18, 25, 7, 14, 30];
$min = 10; $max = 20;
$filtered = array_reduce($numbers, function($carry, $value) use ($min, $max) {
    if ($value >= $min && $value <= $max) {
        $carry[] = $value;
    }
    return $carry;
}, []);

Php получить индекс (получение индекса массива в php)

array_reduce применяет callback к каждому элементу, накапливая результат в переменной $carry. Это альтернатива array_filter, но менее распространена.

Ошибка: забыть передать начальное значение [] – тогда $carry будет null, и попытка добавить элемент через [] вызовет ошибку.

Модификация исходного массива через array_walk

Как изменить исходный массив, удалив неподходящие элементы?


$numbers = [5, 12, 18, 25, 7, 14, 30];
$min = 10; $max = 20;
array_walk($numbers, function(&$value, $key) use ($min, $max) {
    if ($value < $min || $value > $max) {
        unset($value); // не сработает, нужно использовать ссылку на массив и unset по ключу
    }
});

Php значение массива в строку (преобразование массива в строку php)

Важно: array_walk не предназначен для удаления элементов – он передаёт копию значения, если не передавать ссылку. Для удаления лучше использовать цикл foreach с unset($array[$key]).

Типичная ошибка: попытка использовать unset($value) внутри array_walk – это удалит только локальную переменную. Правильно: передать массив по ссылке в callback через use (&$array) или использовать foreach с unset.

Фильтрация ассоциативных массивов с сохранением ключей

Как отфильтровать ассоциативный массив по диапазону значений, не потеряв ключи?


$data = ['a' => 10, 'b' => 25, 'c' => 15, 'd' => 5];
$min = 10; $max = 20;
$filtered = array_filter($data, function($value) use ($min, $max) {
    return $value >= $min && $value <= $max;
});

По умолчанию array_filter сохраняет ключи. Результат: ['a' => 10, 'c' => 15].

Проблема: если нужно получить только числовые индексы, используйте array_values после фильтрации.

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

Как оставить значения, строго больше min, но меньше max?

Заменить >= и <= на > и < соответственно. Для исключения границ: $value > $min && $value < $max.

При работе с числами с плавающей точкой избегайте строгих сравнений из-за погрешностей; используйте небольшой эпсилон.

- Php new array (создание массива в php)
- Php массивы получить первый элемент (получение первых элементов массива в php)
- Php между значениями (выборка значений массива в диапазоне php)

Расширенные примеры фильтрации по диапазону

Пример 1: Фильтрация с комбинацией нескольких диапазонов

Как выбрать значения, попадающие в один из нескольких интервалов?

Пример

$numbers = [5, 12, 18, 25, 7, 14, 30, 45];
$ranges = [[10,20], [30,40]];
$filtered = array_filter($numbers, function($value) use ($ranges) {
    foreach ($ranges as [$min, $max]) {
        if ($value >= $min && $value <= $max) return true;
    }
    return false;
});
print_r($filtered);
Array ( [1] => 12 [2] => 18 [4] => 7? нет, 7 не входит; [5] => 14 [6] => 30 )

Пояснение: для каждого значения проверяется принадлежность хотя бы одному из диапазонов. Обратите внимание на ключи (1,2,5,6).

Пример 2: Фильтрация объектов по свойству

Как получить студентов с возрастом от 20 до 25 лет?

Пример

$students = [
    ['name' => 'Иван', 'age' => 22],
    ['name' => 'Мария', 'age' => 19],
    ['name' => 'Петр', 'age' => 25],
    ['name' => 'Анна', 'age' => 30],
];
$minAge = 20; $maxAge = 25;
$filtered = array_filter($students, function($student) use ($minAge, $maxAge) {
    return $student['age'] >= $minAge && $student['age'] <= $maxAge;
});
print_r($filtered);
Array ( [0] => ['name'=>'Иван','age'=>22] [2] => ['name'=>'Петр','age'=>25] )

Удобно для фильтрации наборов данных. При работе с классами используйте методы геттеры.

Пример 3: Фильтрация с переиндексацией ключей

Как после фильтрации получить массив с последовательными числовыми индексами?

Пример

$numbers = [5, 12, 18, 25];
$min = 10; $max = 20;
$filtered = array_filter($numbers, fn($v) => $v >= $min && $v <= $max);
$reindexed = array_values($filtered);
print_r($reindexed);
Array ( [0] => 12 [1] => 18 )

Используйте стрелочную функцию (PHP 7.4+) для краткости. array_values сбрасывает ключи.

Пример 4: Работа с датами (объекты DateTime)

Как выбрать события, попадающие в временной интервал?

Пример

$dates = [
    new DateTime('2024-01-10'),
    new DateTime('2024-02-15'),
    new DateTime('2024-03-20'),
    new DateTime('2024-05-01'),
];
$start = new DateTime('2024-02-01');
$end = new DateTime('2024-04-01');
$filtered = array_filter($dates, function($date) use ($start, $end) {
    return $date >= $start && $date <= $end;
});
foreach ($filtered as $d) echo $d->format('Y-m-d') . "\n";
2024-02-15
2024-03-20

Объекты DateTime поддерживают сравнение через операторы >=, <=.

Пример 5: Использование генераторов для больших массивов (экономия памяти)

Как обработать массив из миллиона записей без загрузки всего результата в память?

Пример

function filterRangeGenerator(array $array, $min, $max) {
    foreach ($array as $value) {
        if ($value >= $min && $value <= $max) {
            yield $value;
        }
    }
}
$numbers = range(1, 1000000); // условно
$filtered = filterRangeGenerator($numbers, 50000, 50010);
foreach ($filtered as $v) { echo "$v "; } // выведет 50000..50010
50000 50001 50002 50003 50004 50005 50006 50007 50008 50009 50010

Генератор возвращает значения по одному, не создавая массив в памяти. Подходит для потоковой обработки.

Пример 6: Фильтрация с условием 'между' с помощью array_uintersect (нестандартный подход)

Можно ли использовать пересечение массивов для диапазона?

Только если диапазон задан набором точных значений. Для непрерывного диапазона не подходит. Но как курьёз: $result = array_uintersect($numbers, range($min, $max), 'strcasecmp'); – сравнение строк, ненадёжно.

Пример

$numbers = [1,5,10,15,20];
$range = range(5,15);
$result = array_intersect($numbers, $range);
print_r($result); // [1=>5,2=>10,3=>15]
Array ( [1] => 5 [2] => 10 [3] => 15 )

Важно: array_intersect сравнивает значения, а не интервал. Поэтому работает только для точных попаданий.

Пример 7: Фильтрация с исключением границ и с плавающей точкой

Пример

$values = [1.0, 1.5, 2.0, 2.5, 3.0];
$min = 1.1; $max = 2.4;
$filtered = array_filter($values, function($v) use ($min, $max) {
    return $v > $min && $v < $max;
});
// учёт погрешности: $epsilon = 0.0001; return $v > $min - $epsilon && $v < $max + $epsilon;
[1=>1.5, 3=>2.0? нет, 2.0 не меньше 2.4, 2.0 попадает? если строго меньше, то 2.0 попадает? 2.0 < 2.4, да. 2.5 не подходит]
На самом деле результат: [1.5, 2.0].

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

Выборка значений массива в диапазоне PHP - comments

En
Php между значениями (php)