Reduce
July 26, 2026 · View on GitHub
Инструменты для редуцирования итерируемых коллекций к единственному значению.
To Average
Возвращает среднее арифметическое элементов коллекции.
Для пустой коллекции возвращает null.
Reduce::toAverage(iterable $data): float
use IterTools\Reduce;
$grades = [100, 90, 95, 85, 94];
$finalGrade = Reduce::toAverage($numbers);
// 92.8
To Count
Возвращает длину данной коллекции.
Reduce::toCount(iterable $data): int
use IterTools\Reduce;
$someIterable = ImportantThing::getCollectionAsIterable();
$length = Reduce::toCount($someIterable);
// 3
To Count By
Сворачивает коллекцию в массив количеств, сгруппированных по значению, которое возвращает функция-ключ.
Reduce::toCountBy(iterable $data, callable $keyFunc): array
Функция-ключ должна возвращать int или string (единственные допустимые типы ключей массива). При любом другом типе возвращаемого значения выбрасывается \TypeError с указанием некорректного типа.
Примечание: массивы PHP приводят числовые строки-ключи к целым числам — функция-ключ, возвращающая строку
"1", и функция-ключ, возвращающая целое1, объединяются в один целочисленный ключ1с суммарным количеством.
use IterTools\Reduce;
$words = ['apple', 'pear', 'banana', 'kiwi', 'plum'];
$counts = Reduce::toCountBy($words, fn ($word) => \strlen($word));
// [5 => 1, 4 => 3, 6 => 1]
To First
Возвращает первый элемент коллекции.
Reduce::toFirst(iterable $data): mixed
Бросает \LengthException если коллекция пуста.
use IterTools\Reduce;
$input = [10, 20, 30];
$result = Reduce::toFirst($input);
// 10
To First And Last
Возвращает первый и последний элементы коллекции.
Reduce::toFirstAndLast(iterable $data): array{mixed, mixed}
Бросает \LengthException если хранимая в потоке коллекция пуста.
use IterTools\Reduce;
$input = [10, 20, 30];
$result = Reduce::toFirstAndLast($input);
// [10, 30]
To First Match
Возвращает первый элемент коллекции, удовлетворяющий предикату.
Reduce::toFirstMatch(iterable $data, callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Завершает обход на первом совпадении — коллекция не потребляется полностью.
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Reduce;
$numbers = [1, 3, 5, 6, 7, 8];
$firstEven = Reduce::toFirstMatch($numbers, fn (int $n) => $n % 2 === 0);
// 6
To First Match Index
Возвращает индекс (отсчёт от нуля) первого элемента, удовлетворяющего предикату.
Reduce::toFirstMatchIndex(iterable $data, callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Завершает обход на первом совпадении — коллекция не потребляется полностью.
- Возвращает
$default(по умолчаниюnull), если совпадений нет. - Позиция всегда отсчитывается от начала обхода, независимо от исходных ключей.
use IterTools\Reduce;
$numbers = [10, 20, 30, 40];
$firstOver25Index = Reduce::toFirstMatchIndex($numbers, fn (int $n) => $n > 25);
// 2
use IterTools\Reduce;
// Ленивый поиск с ранним выходом: генератор, который бросил бы исключение
// после совпадения, никогда не продвигается дальше совпадающей позиции.
$ids = (function (): \Generator {
yield 1;
yield 2;
yield 3;
throw new \RuntimeException('iterator advanced past match');
})();
$index = Reduce::toFirstMatchIndex($ids, fn (int $n) => $n === 2);
// 1
To First Match Key
Возвращает ключ исходной коллекции для первого элемента, удовлетворяющего предикату.
Reduce::toFirstMatchKey(iterable $data, callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Завершает обход на первом совпадении — коллекция не потребляется полностью.
- Возвращает
$default(по умолчаниюnull), если совпадений нет. - Сохраняет исходный ключ (строковый для ассоциативных коллекций, целочисленный для списков).
use IterTools\Reduce;
$users = ['alice' => 12, 'bob' => 17, 'carol' => 22, 'dan' => 30];
$firstAdultName = Reduce::toFirstMatchKey($users, fn (int $age) => $age >= 18);
// 'carol'
use IterTools\Reduce;
$prices = ['usd' => 9.99, 'eur' => 8.49, 'jpy' => 1499.0];
$firstExpensiveCurrency = Reduce::toFirstMatchKey(
$prices,
fn (float $p) => $p > 1000,
'none'
);
// 'jpy'
To Last
Возвращает последний элемент коллекции.
Reduce::toLast(iterable $data): mixed
Бросает \LengthException если коллекция пуста.
use IterTools\Reduce;
$input = [10, 20, 30];
$result = Reduce::toLast($input);
// 30
To Last Match
Возвращает последний элемент коллекции, удовлетворяющий предикату.
Reduce::toLastMatch(iterable $data, callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Полностью потребляет коллекцию (без раннего выхода).
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Reduce;
$numbers = [1, 3, 5, 6, 7, 8, 9];
$lastEven = Reduce::toLastMatch($numbers, fn (int $n) => $n % 2 === 0);
// 8
$lastNegative = Reduce::toLastMatch($numbers, fn (int $n) => $n < 0, 'none');
// 'none'
To Last Match Index
Возвращает индекс (отсчёт от нуля) последнего элемента, удовлетворяющего предикату.
Reduce::toLastMatchIndex(iterable $data, callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Полностью потребляет коллекцию.
- Возвращает
$default(по умолчаниюnull), если совпадений нет. - Для ассоциативных коллекций возвращает позицию (а не исходный ключ).
use IterTools\Reduce;
$numbers = [10, 20, 30, 40, 5];
$lastOver25Index = Reduce::toLastMatchIndex($numbers, fn (int $n) => $n > 25);
// 3
To Last Match Key
Возвращает ключ исходной коллекции для последнего элемента, удовлетворяющего предикату.
Reduce::toLastMatchKey(iterable $data, callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Полностью потребляет коллекцию.
- Возвращает
$default(по умолчаниюnull), если совпадений нет. - Сохраняет исходный ключ (строковый для ассоциативных коллекций, целочисленный для списков).
use IterTools\Reduce;
$users = ['alice' => 12, 'bob' => 17, 'carol' => 22, 'dan' => 30];
$lastAdultName = Reduce::toLastMatchKey($users, fn (int $age) => $age >= 18);
// 'dan'
To Max
Возвращает максимальный элемент коллекции.
Reduce::toMax(iterable $data, callable $compareBy = null): mixed|null
- Функция
$compareByдолжна возвращать сравнимое значение. - Если аргумент
$compareByне передан, элементы коллекции должны быть сравнимы. - Для пустой коллекции возвращает
null.
use IterTools\Reduce;
$numbers = [5, 3, 1, 2, 4];
$result = Reduce::toMax($numbers);
// 5
$movieRatings = [
[
'title' => 'Star Wars: Episode IV - A New Hope',
'rating' => 4.6
],
[
'title' => 'Star Wars: Episode V - The Empire Strikes Back',
'rating' => 4.8
],
[
'title' => 'Star Wars: Episode VI - Return of the Jedi',
'rating' => 4.6
],
];
$compareBy = fn ($movie) => $movie['rating'];
$highestRatedMovie = Reduce::toMax($movieRatings, $compareBy);
// [
// 'title' => 'Star Wars: Episode V - The Empire Strikes Back',
// 'rating' => 4.8
// ];
To Median
Возвращает медиану коллекции.
Reduce::toMedian(iterable $data): int|float|null
- Для чётного количества элементов медиана равна среднему арифметическому двух средних значений; вычисление не переполняется, даже если сумма двух средних значений превышает
PHP_FLOAT_MAX, и не теряет точность, если их размах выходит за пределы целочисленного диапазона (toMedian([PHP_INT_MIN, PHP_INT_MAX])равно-0.5, а не0.0). Два одинаковых средних значения дают само это значение, включаяINF. - Для пустой коллекции возвращает
null.
use IterTools\Reduce;
$grades = [100, 90, 95, 85, 94];
$median = Reduce::toMedian($grades);
// 94
To Min
Возвращает минимальный элемент коллекции.
Reduce::toMin(iterable $data, callable $compareBy = null): mixed|null
- Функция
$compareByдолжна возвращать сравнимое значение. - Если аргумент
$compareByне передан, элементы коллекции должны быть сравнимы. - Для пустой коллекции возвращает
null.
use IterTools\Reduce;
$numbers = [5, 3, 1, 2, 4];
$result = Reduce::toMin($numbers);
// 1
$movieRatings = [
[
'title' => 'The Matrix',
'rating' => 4.7
],
[
'title' => 'The Matrix Reloaded',
'rating' => 4.3
],
[
'title' => 'The Matrix Revolutions',
'rating' => 3.9
],
[
'title' => 'The Matrix Resurrections',
'rating' => 2.5
],
];
$compareBy = fn ($movie) => $movie['rating'];
$lowestRatedMovie = Reduce::toMin($movieRatings, $compareBy);
// [
// 'title' => 'The Matrix Resurrections',
// 'rating' => 2.5
// ]
To Min Max
Возвращает минимальный и максимальный элементы коллекции.
Reduce::toMinMax(iterable $numbers, callable $compareBy = null): array
- Функция
$compareByдолжна возвращать сравнимое значение. - Если аргумент
$compareByне передан, элементы коллекции должны быть сравнимы. - Для пустой коллекции возвращает
[null, null].
use IterTools\Reduce;
$numbers = [1, 2, 7, -1, -2, -3];;
[$min, $max] = Reduce::toMinMax($numbers);
// [-3, 7]
$reportCard = [
[
'subject' => 'history',
'grade' => 90
],
[
'subject' => 'math',
'grade' => 98
],
[
'subject' => 'science',
'grade' => 92
],
[
'subject' => 'english',
'grade' => 85
],
[
'subject' => 'programming',
'grade' => 100
],
];
$compareBy = fn ($class) => $class['grade'];
$bestAndWorstSubject = Reduce::toMinMax($reportCard, $compareBy);
// [
// [
// 'subject' => 'english',
// 'grade' => 85
// ],
// [
// 'subject' => 'programming',
// 'grade' => 100
// ],
// ]
To Mode
Возвращает список мод коллекции (наиболее часто встречающихся значений).
Reduce::toMode(iterable $data): array
- Возвращает все значения с максимальной частотой в порядке первого появления (для коллекции без повторов возвращаются все её значения).
- Для мультимодальных данных возвращается несколько мод.
- Значения сравниваются строго, поэтому
1,1.0и'1'считаются различными. - Для пустой коллекции возвращает пустой массив.
use IterTools\Reduce;
$votes = ['red', 'blue', 'red', 'green', 'blue', 'red'];
$modes = Reduce::toMode($votes);
// ['red']
To Nth
Возвращает n-й элемент коллекции.
Reduce::toNth(iterable $data, int $position): mixed
use IterTools\Reduce;
$lotrMovies = ['The Fellowship of the Ring', 'The Two Towers', 'The Return of the King'];
$rotk = Reduce::toNth($lotrMovies, 2);
// 20
To Only
Возвращает единственный элемент коллекции.
Reduce::toOnly(iterable $data): mixed
- Бросает
\LengthException, если коллекция пуста или содержит более одного элемента. - Для ассоциативной коллекции с одним элементом возвращает значение (не ключ).
- Для проверки «совпадает ровно один элемент» используйте композицию
Stream::filter()->toOnly().
use IterTools\Reduce;
$config = ['admin' => 'jane'];
$onlyAdmin = Reduce::toOnly($config);
// 'jane'
use IterTools\Reduce;
Reduce::toOnly([]); // бросает \LengthException
Reduce::toOnly([1, 2, 3]); // бросает \LengthException
To Percentile
Возвращает значение коллекции для заданного процентиля.
Reduce::toPercentile(iterable $data, float $percentile): int|float|null
- Используется метод R-7 / линейной интерполяции (по умолчанию в NumPy). Процентиль
0— это минимум,100— максимум. - Аргумент
$percentileдолжен находиться в диапазоне[0, 100]; иначе выбрасывается\InvalidArgumentException. - Интерполяция не переполняется, даже если расстояние между двумя соседними значениями превышает
PHP_FLOAT_MAX. - Процентиль
50для любых входных данных возвращает ровно то же, что иtoMedian. - Для пустой коллекции возвращает
null.
use IterTools\Reduce;
$scores = [10, 20, 30, 40, 50];
$p75 = Reduce::toPercentile($scores, 75);
// 40
To Product
Возвращает произведение элементов коллекции.
Для пустой коллекции возвращает null.
Reduce::toProduct(iterable $data): number|null
use IterTools\Reduce;
$primeFactors = [5, 2, 2];
$number = Reduce::toProduct($primeFactors);
// 20
To Quantile
Возвращает значение коллекции для заданного квантиля.
Reduce::toQuantile(iterable $data, float $quantile): int|float|null
- Тонкая обёртка над
toPercentile, принимающая квантиль в диапазоне[0, 1](например,0.25— первый квартиль / 25-й процентиль). - Аргумент
$quantileдолжен находиться в диапазоне[0, 1]; иначе выбрасывается\InvalidArgumentException. - Для пустой коллекции возвращает
null.
use IterTools\Reduce;
$scores = [10, 20, 30, 40, 50];
$q3 = Reduce::toQuantile($scores, 0.75);
// 40
To Random Value
Возвращает случайный элемент из коллекции.
Reduce::toRandomValue(iterable $data): mixed
use IterTools\Reduce;
$sfWakeupOptions = ['mid', 'low', 'overhead', 'throw', 'meaty'];
$wakeupOption = Reduce::toRandomValue($sfWakeupOptions);
// e.g., throw
To Range
Возвращает разность максимального и минимального элементов коллекции.
Reduce::toRange(iterable $numbers): int|float
Для пустой коллекции возвращает 0.
use IterTools\Reduce;
$grades = [100, 90, 80, 85, 95];
$range = Reduce::toRange($numbers);
// 20
To Standard Deviation
Возвращает стандартное отклонение значений коллекции.
Reduce::toStandardDeviation(iterable $data, bool $sample = false): float|null
- Квадратный корень из дисперсии. По умолчанию — стандартное отклонение генеральной совокупности; при
$sample = true— выборочное стандартное отклонение (поправка Бесселя). - Наследует от
toVarianceоднопроходность, памятьO(1)и поведение при переполнении. - Возвращает
nullдля пустой коллекции или для выборочного стандартного отклонения единственного значения. Стандартное отклонение генеральной совокупности для единственного значения равно0.0. - Случаи с
nullимеют приоритет надNAN, как и вtoVariance:toStandardDeviation([INF], true)возвращаетnull, аtoStandardDeviation([INF])—NAN.
use IterTools\Reduce;
$numbers = [2, 4, 4, 4, 5, 5, 7, 9];
$populationStdDev = Reduce::toStandardDeviation($numbers);
// 2.0
$sampleStdDev = Reduce::toStandardDeviation($numbers, true);
// 2.138...
To String
Преобразует коллекцию в строку, "склеивая" ее элементы.
- Значение необязательного аргумента
$separatorвставляется в качестве разделителя между элементами в строке. - Значение необязательного аргумента
$prefixвставляется в начало строки. - Значение необязательного аргумента
$suffixвставляется в конец строки.
Reduce::toString(iterable $data, string $separator = '', string $prefix = '', string $suffix = ''): string
use IterTools\Reduce;
$words = ['IterTools', 'PHP', 'v1.0'];
$string = Reduce::toString($words);
// IterToolsPHPv1.0
$string = Reduce::toString($words, '-');
// IterTools-PHP-v1.0
$string = Reduce::toString($words, '-', 'Library: ');
// Library: IterTools-PHP-v1.0
$string = Reduce::toString($words, '-', 'Library: ', '!');
// Library: IterTools-PHP-v1.0!
To Sum
Возвращает сумму элементов коллекции.
Reduce::toSum(iterable $data): number
use IterTools\Reduce;
$parts = [10, 20, 30];
$sum = Reduce::toSum($parts);
// 60
To Value
Редуцирует коллекцию до значения, вычисляемого с использованием callback-функции.
Reduce::toValue(iterable $data, callable $reducer, mixed $initialValue): mixed
use IterTools\Reduce;
$input = [1, 2, 3, 4, 5];
$sum = fn ($carry, $item) => $carry + $item;
$result = Reduce::toValue($input, $sum, 0);
// 15
To Variance
Возвращает дисперсию значений коллекции.
Reduce::toVariance(iterable $data, bool $sample = false): float|null
- По умолчанию — дисперсия генеральной совокупности; при
$sample = true— выборочная дисперсия (поправка Бесселя, деление наN - 1). - Используется масштабированный онлайн-алгоритм с компенсированным текущим средним: один проход по коллекции с памятью
O(1), поэтому коллекция не материализуется и большие ленивые итерируемые объекты безопасны. - Результат устойчив к порядку входных данных с точностью до ошибок округления, но не воспроизводится побитово: сложение чисел с плавающей точкой неассоциативно, поэтому разные порядки могут отличаться на последний ulp. Компенсированное среднее устраняет грубую зависимость от порядка при большом смещении с малым разбросом (например,
1e16, 1e16 + 2, 1e16 + 4, где иначе ответ менялся бы на 50% в зависимости от порядка). - Остаётся конечным всегда, когда дисперсия представима, даже если промежуточные величины уже нет: дисперсия
[-1.4e154, 1.4e154, 0]равна~1.31e308, хотя дисперсия её первых двух значений (1.96e308) уже превышаетPHP_FLOAT_MAX. - Любое неконечное значение во входных данных даёт
NAN, так как отклонения от бесконечного среднего — этоINF - INF. Дисперсия, которую действительно невозможно представить, возвращается какINF, но никогда как отрицательное число. - Возвращает
nullдля пустой коллекции или для выборочной дисперсии единственного значения (N - 1 = 0не определено). Дисперсия генеральной совокупности для единственного значения равна0.0. - Случаи с
nullимеют приоритет надNAN:toVariance([INF], true)возвращаетnull, а неNAN, так как по одному наблюдению выборочную дисперсию вычислить нельзя в принципе, каким бы это наблюдение ни было. Дисперсия генеральной совокупности для одного значения определена, поэтомуtoVariance([INF])возвращаетNAN.
use IterTools\Reduce;
$numbers = [1, 2, 3, 4, 5];
$populationVariance = Reduce::toVariance($numbers);
// 2.0
$sampleVariance = Reduce::toVariance($numbers, true);
// 2.5
Consume
Полностью обходит коллекцию, отбрасывая значения.
Reduce::consume(iterable $data): void
- Полезно для принудительного выполнения «ленивого» конвейера, нужного только ради побочных эффектов.
- Ничего не возвращает.
use IterTools\Reduce;
use IterTools\Single;
$log = [];
$pipeline = Single::map([1, 2, 3], function (int $n) use (&$log): int {
$log[] = $n;
return $n * 2;
});
// $log === [] (Single::map ленивая — пока ничего не выполнилось)
Reduce::consume($pipeline);
// $log === [1, 2, 3]