Цепочечный вызов итераторов
July 26, 2026 · View on GitHub
Предоставляет гибкий текучий интерфейс для преобразования массивов и других итерируемых сущностей с помощью конвейера операций.
Данный функционал содержит в себе:
- Фабричные методы для создания объекта, предоставляющего текучий интерфейс для работы с итерируемыми сущностями.
- Методы для преобразования текущего состояние потока в новый поток.
- Способы завершения потока преобразований:
- Методы, преобразующие поток в скалярное значение или в структуру данных.
$result = Stream::of([1, 1, 2, 2, 3, 4, 5]) ->distinct() // [1, 2, 3, 4, 5] ->map(fn ($x) => $x**2) // [1, 4, 9, 16, 25] ->filterTrue(fn ($x) => $x < 10) // [1, 4, 9] ->toSum(); // 14- Возможность проитерировать результат потока на любом этапе с использованием цикла
foreach.
$result = Stream::of([1, 1, 2, 2, 3, 4, 5]) ->distinct() // [1, 2, 3, 4, 5] ->map(fn ($x) => $x**2) // [1, 4, 9, 16, 25] ->filterTrue(fn ($x) => $x < 10); // [1, 4, 9] foreach ($result as $item) { // 1, 4, 9 }
Фабричные методы
Of
Создает поток из данной коллекции.
Stream::of(iterable $iterable): Stream
use IterTools\Stream;
$iterable = [1, 2, 3];
$result = Stream::of($iterable)
->chainWith([4, 5, 6], [7, 8, 9])
->zipEqualWith([1, 2, 3, 4, 5, 6, 7, 8, 9])
->toValue(fn ($carry, $item) => $carry + array_sum($item));
// 90
Of Coin Flips
Создает поток из бесконечных случайных бросков монеты.
Stream::ofCoinFlips(int $repetitions): Stream
use IterTools\Stream;
$result = Stream::ofCoinFlips(10)
->filterTrue()
->toCount();
// 5 (random)
Of CSV File
Создает поток из строк CSV-файла.
Stream::ofCsvFile(resource $fileHandle, string $separator = ',', string $enclosure = '"', string = $escape = '\\'): Stream
use IterTools\Stream;
$fileHandle = \fopen('path/to/file.csv', 'r');
$result = Stream::of($fileHandle)
->toArray();
Of CSV File Assoc
Создает поток из строк CSV-файла как ассоциативных массивов с ключами из заголовков.
Stream::ofCsvFileAssoc(resource $fileHandle, ?array $headers = null, string $separator = ',', string $enclosure = '"', string $escape = '\\'): Stream
Если $headers равен null, первая строка файла потребляется и используется как список заголовков. Иначе используются переданные $headers, а каждая строка считается данными.
use IterTools\Stream;
$fileHandle = \fopen('path/to/file.csv', 'r');
$result = Stream::ofCsvFileAssoc($fileHandle)
->toArray();
// [['header1' => 'value1', ...], ...]
Of Empty
Создает поток из пустой коллекции.
Stream::ofEmpty(): Stream
use IterTools\Stream;
$result = Stream::ofEmpty()
->chainWith([1, 2, 3])
->toArray();
// 1, 2, 3
Of File Lines
Создает поток из строк файла.
Stream::ofFileLines(resource $fileHandle): Stream
use IterTools\Stream;
$fileHandle = \fopen('path/to/file.txt', 'r');
$result = Stream::of($fileHandle)
->map('strtoupper');
->toArray();
Of Random Choice
Создает поток из бесконечных случайных выборов элемента из списка.
Stream::ofRandomChoice(array $items, int $repetitions): Stream
use IterTools\Stream;
$languages = ['PHP', 'Go', 'Python'];
$languages = Stream::ofRandomChoice($languages, 5)
->toArray();
// 'Go', 'PHP', 'Python', 'PHP', 'PHP' (random)
Of Random Numbers
Создает поток из бесконечного набора случайных целых чисел.
Stream::ofRandomNumbers(int $min, int $max, int $repetitions): Stream
use IterTools\Stream;
$min = 1;
$max = 3;
$reps = 7;
$result = Stream::ofRandomNumbers($min, $max, $reps)
->toArray();
// 1, 2, 2, 1, 3, 2, 1 (random)
Of Random Percentage
Создает поток из бесконечного набора случайных вещественных чисел между 0 и 1.
Stream::ofRandomPercentage(int $repetitions): Stream
use IterTools\Stream;
$stream = Stream::ofRandomPercentage(3)
->toArray();
// 0.8012566976245, 0.81237281724151, 0.61676896329459 [random]
Of Range
Создает ленивый поток конечной арифметической прогрессии чисел.
Stream::ofRange(int|float|string $start, int|float|string $end, int|float $step = 1): Stream
- Числовые строки (например,
"1","1.5","1e3","01") допустимы и приводятся кint/floatперед итерацией. Не-числовые строки (например,"a") приводят к\InvalidArgumentException. - Направление выводится из соотношения
$startи$end. Отрицательный$stepдопустим только при убывающем направлении. - Выбрасывает
\InvalidArgumentException, если какой-либо операнд не является конечным (в том числе числовые строки вроде"1e309", переполняющиеся вINF), если$step == 0, если знак шага конфликтует с направлением операндов или еслиabs($step) > abs($end - $start). - Ленивый поток — безопасно работает с большими границами совместно с downstream-операциями вроде
limit.
use IterTools\Stream;
$numbers = Stream::ofRange(0, 5)
->toArray();
// 0, 1, 2, 3, 4, 5
$descending = Stream::ofRange(5, 1)
->toArray();
// 5, 4, 3, 2, 1
$firstFive = Stream::ofRange(1, PHP_INT_MAX)
->limit(5)
->toArray();
// 1, 2, 3, 4, 5
Примечание: до этого релиза
Stream::ofRangeматериализовал всю последовательность через\range()и при подаче двух числовых строк без ведущих нулей сохранял строковый тип на выходе (например,ofRange("1", "5")возвращал["1", ..., "5"]). Ленивая реализация приводит все числовые строки кint/float. Она также фиксирует числовую семантику встроенной функции\range()из PHP 8.3+ на всех поддерживаемых версиях PHP: шаг типа float с целым значением при целочисленных операндах теперь даётint(ofRange(1, 5, 1.0)→[1, 2, 3, 4, 5]), тогда как в PHP 8.2 ранее возвращались float.
Of Rock Paper Scissors
Создает поток из бесконечных случайных выборов "камень-ножницы-бумага".
Stream::ofRockPaperScissors(int $repetitions): Stream
use IterTools\Stream;
$rps = Stream::ofRockPaperScissors(5)
->toArray();
// 'paper', 'rock', 'rock', 'scissors', 'paper' [random]
Цепочечные операции
Accumulate
Накапливает результат применения бинарного оператора по элементам потока.
$stream->accumulate(callable $op, mixed ...$initial): Stream
- Без начального значения: первый элемент результата — первый элемент коллекции без изменений, каждый следующий —
$op(аккумулятор, следующий_элемент). - С начальным значением: первый элемент результата — начальное значение, каждый следующий —
$op(аккумулятор, следующий_элемент). - Явный
nullявляется допустимым начальным значением. - Выбрасывает
\InvalidArgumentException, если передано более одного начального значения.
use IterTools\Stream;
$numbers = [1, 2, 3, 4, 5];
$runningSums = Stream::of($numbers)
->accumulate(fn ($a, $b) => $a + $b)
->toArray();
// [1, 3, 6, 10, 15]
$withInitial = Stream::of($numbers)
->accumulate(fn ($a, $b) => $a + $b, 100)
->toArray();
// [100, 101, 103, 106, 110, 115]
ASort
Сортирует коллекцию в потоке с сохранением ключей.
$stream->asort(?callable $comparator = null)
Если $comparator не передан, элементы хранимой коллекции должны быть сравнимы.
use IterTools\Stream;
$worldPopulations = [
'China' => 1_439_323_776,
'India' => 1_380_004_385,
'Indonesia' => 273_523_615,
'USA' => 331_002_651,
];
$result = Stream::of($worldPopulations)
->filter(fn ($pop) => $pop > 300_000_000)
->asort()
->toAssociativeArray();
// USA => 331_002_651,
// India => 1_380_004_385,
// China => 1_439_323_776,
Chain With
Добавляет в конец потокового итератора другие коллекции для последовательного итерирования.
$stream->chainWith(iterable ...$iterables): Stream
Создает одну длинную последовательность из последовательности в потоке и нескольких данных последовательностей.
use IterTools\Stream;
$input = [1, 2, 3];
$result = Stream::of($input)
->chainWith([4, 5, 6])
->chainWith([7, 8, 9])
->toArray();
// 1, 2, 3, 4, 5, 6, 7, 8, 9
Product With
Декартово произведение коллекции потока с другими коллекциями.
$stream->productWith(iterable ...$iterables): Stream
Выходные кортежи — массивы-списки (индексы с нуля, в порядке входов). Без дополнительных коллекций каждый элемент потока оборачивается в одноэлементный кортеж. Если хотя бы одна коллекция (поток или аргумент) пуста, результат пуст.
use IterTools\Stream;
$numbers = [1, 2];
$letters = ['a', 'b'];
$result = Stream::of($numbers)
->productWith($letters)
->toArray();
// [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]
Permutations
Перестановки элементов коллекции потока.
$stream->permutations(?int $r = null): Stream
Выходные кортежи — массивы-списки (индексы с нуля, в порядке входа). Порядок соответствует itertools.permutations из Python (лексикографический по позиции): одинаковые значения различаются по позиции. $r = 0 даёт один пустой кортеж; если $r больше длины потока, результат пуст; $r = null означает перестановки полной длины.
Выбрасывает \InvalidArgumentException, если $r отрицательное.
use IterTools\Stream;
$data = [1, 2, 3];
$result = Stream::of($data)
->permutations(2)
->toArray();
// [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
Combinations
Сочетания (без повторений) элементов коллекции потока.
$stream->combinations(int $r): Stream
Выходные кортежи — массивы-списки (индексы с нуля, в порядке входа). Порядок соответствует itertools.combinations из Python (лексикографический по позиции): одинаковые значения различаются по позиции. $r = 0 даёт один пустой кортеж; если $r больше длины потока, результат пуст.
Выбрасывает \InvalidArgumentException, если $r отрицательное.
use IterTools\Stream;
$data = [1, 2, 3, 4];
$result = Stream::of($data)
->combinations(2)
->toArray();
// [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
Combinations With Replacement
Сочетания с повторениями элементов коллекции потока.
$stream->combinationsWithReplacement(int $r): Stream
Выходные кортежи — массивы-списки (индексы с нуля, в порядке входа). Порядок соответствует itertools.combinations_with_replacement из Python (лексикографический по позиции): одинаковые значения различаются по позиции и могут давать дублирующиеся выходные кортежи. В отличие от combinations(), $r может превышать длину потока — элементы повторяются. $r = 0 даёт один пустой кортеж.
Выбрасывает \InvalidArgumentException, если $r отрицательное.
use IterTools\Stream;
$data = [1, 2, 3];
$result = Stream::of($data)
->combinationsWithReplacement(2)
->toArray();
// [[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]]
Powerset
Все подмножества элементов потока, упорядоченные по длине, а внутри каждой длины — по позиции во входе.
$stream->powerset(): Stream
Подмножества — массивы-списки (индексы с нуля, в порядке входа); ключи источника отбрасываются. Подмножества отдаются в порядке возрастания длины; внутри каждой длины порядок совпадает с Stream::combinations (лексикографический по позиции): дублирующиеся значения уникальны по позиции. Пустой поток даёт одно пустое подмножество.
Внимание: поток из
nэлементов даёт2**nподмножеств — расход растёт экспоненциально.
use IterTools\Stream;
$data = [1, 2, 3];
$result = Stream::of($data)
->powerset()
->toArray();
// [[], [1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]]
use IterTools\Stream;
// Все комбинации фича-флагов для параметризованных тестов.
$result = Stream::of(['darkMode', 'beta', 'analytics'])
->powerset()
->toArray();
// [[], ['darkMode'], ['beta'], ['analytics'],
// ['darkMode', 'beta'], ['darkMode', 'analytics'], ['beta', 'analytics'],
// ['darkMode', 'beta', 'analytics']]
См. также Combinatorics::powerset.
Compress
Отфильтровывает из потока элементы, которые не выбраны.
$stream->compress(iterable $selectors): Stream
Массив селекторов уточняет, какие элементы помещать в выборку (значение селектора 1),
а какие исключать (значение селектора 0).
use IterTools\Stream;
$input = [1, 2, 3];
$result = Stream::of($input)
->compress([0, 1, 1])
->toArray();
// 2, 3
Compress Associative
Выбирает из хранимой коллекции элементы по заданным ключам.
$stream->compressAssociative(array $keys): Stream
- Ключами могут быть только строки или целые числа (по аналогии с ключами PHP-массивов).
use IterTools\Stream;
$starWarsEpisodes = [
'I' => 'The Phantom Menace',
'II' => 'Attack of the Clones',
'III' => 'Revenge of the Sith',
'IV' => 'A New Hope',
'V' => 'The Empire Strikes Back',
'VI' => 'Return of the Jedi',
'VII' => 'The Force Awakens',
'VIII' => 'The Last Jedi',
'IX' => 'The Rise of Skywalker',
];
$sequelTrilogyNumbers = ['VII', 'VIII', 'IX'];
$sequelTrilogy = Stream::of($starWarsEpisodes)
->compressAssociative($sequelTrilogyNumbers)
->toAssociativeArray();
// 'VII' => 'The Force Awakens',
// 'VIII' => 'The Last Jedi',
// 'IX' => 'The Rise of Skywalker',
Chunkwise
Итерирует элементы из потока с разбиением по чанкам.
$stream->chunkwise(int $chunkSize): Stream
Минимальный размер чанка — 1.
use IterTools\Stream;
$friends = ['Ross', 'Rachel', 'Chandler', 'Monica', 'Joey'];
$result = Stream::of($friends)
->chunkwise(2)
->toArray();
// ['Ross', 'Rachel'], ['Chandler', 'Monica'], ['Joey']
Chunkwise Overlap
Итерирует элементы из потока с разбиением по взаимонакладывающимся чанкам.
$stream->chunkwiseOverlap(int $chunkSize, int $overlapSize, bool $includeIncompleteTail = true): Stream
- Минимальный размер чанка — 1.
- Размер наложения должен быть меньше длины чанка.
- См. также Windowed — основанный на шаге аналог, дополнительно поддерживающий окна с пропусками (
$step > $size).
use IterTools\Stream;
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
$result = Stream::of($friends)
->chunkwiseOverlap(3, 1)
->toArray()
// [1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]
Distinct
Фильтрует элементы из потока, сохраняя только уникальные значения.
$stream->distinct(bool $strict = true): Stream
По умолчанию выполняет сравнения в режиме строгой типизации. Передайте значение false аргумента $strict, чтобы работать в режиме приведения типов.
use IterTools\Stream;
$input = [1, 2, 1, 2, 3, 3, '1', '1', '2', '3'];
$stream = Stream::of($input)
->distinct()
->toArray();
// 1, 2, 3, '1', '2', '3'
$stream = Stream::of($input)
->distinct(false)
->toArray();
// 1, 2, 3
Distinct By
Возвращает поток, фильтрующий элементы и оставляющий только уникальные значения согласно заданной функции сравнения.
$stream->distinctBy(callable $compareBy): Stream
use IterTools\Stream;
$streetFighterConsoleReleases = [
['id' => '112233', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'Dreamcast'],
['id' => '223344', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'PS4'],
['id' => '334455', 'name' => 'Street Fighter 3 3rd Strike', 'console' => 'PS5'],
['id' => '445566', 'name' => 'Street Fighter VI', 'console' => 'PS4'],
['id' => '556677', 'name' => 'Street Fighter VI', 'console' => 'PS5'],
['id' => '667799', 'name' => 'Street Fighter VI', 'console' => 'PC'],
];
$stream = Stream::of($streetFighterConsoleReleases)
->distinctBy(fn ($sfTitle) => $sfTitle['name'])
->toArray();
// Содержит одну запись для SF3 3rd Strike и одну для SFVI
Distinct Adjacent
Возвращает поток, удаляющий только подряд идущие дубликаты (поведение Unix uniq).
$stream->distinctAdjacent(): Stream
- Каждый элемент сравнивается строго (
===) с предыдущим выданным элементом. - Не подряд идущие дубликаты сохраняются.
- Работает с памятью O(1) — хранится только предыдущий элемент.
- Исходные ключи отбрасываются.
use IterTools\Stream;
$result = Stream::of([1, 1, 2, 2, 3, 1, 1])
->distinctAdjacent()
->toArray();
// [1, 2, 3, 1]
use IterTools\Stream;
$logLines = ['error: timeout', 'error: timeout', 'info: ok', 'error: timeout', 'error: timeout'];
$collapsed = Stream::of($logLines)
->distinctAdjacent()
->toArray();
// ['error: timeout', 'info: ok', 'error: timeout']
См. также Set::distinctAdjacent.
Distinct Adjacent By
Возвращает поток, удаляющий только подряд идущие дубликаты по ключу, используя заданную функцию ключа.
$stream->distinctAdjacentBy(callable $keyFn): Stream
- Извлечённый ключ каждого элемента сравнивается строго (
===) с ключом предыдущего элемента. - Не подряд идущие дубликаты по ключу сохраняются.
- Работает с памятью O(1) и вызывает
$keyFnровно один раз на элемент. - Исходные ключи отбрасываются.
use IterTools\Stream;
$words = ['apple', 'ant', 'banana', 'berry', 'apple'];
$firstLetterRuns = Stream::of($words)
->distinctAdjacentBy(fn ($s) => $s[0])
->toArray();
// ['apple', 'banana', 'apple']
use IterTools\Stream;
$readings = [
['ts' => 60, 'v' => 1],
['ts' => 65, 'v' => 2],
['ts' => 119, 'v' => 3],
['ts' => 120, 'v' => 4],
['ts' => 121, 'v' => 5],
];
$compressed = Stream::of($readings)
->distinctAdjacentBy(fn ($r) => intdiv($r['ts'], 60))
->toArray();
// [['ts' => 60, 'v' => 1], ['ts' => 120, 'v' => 4]]
См. также Set::distinctAdjacentBy.
Drop Last
Перебирает все элементы потока, кроме последних $count.
$stream->dropLast(int $count): Stream
Один проход на основе очереди: последние $count элементов никогда не возвращаются. Если $count равен 0, возвращаются все элементы; если $count больше или равен длине потока, не возвращается ничего. Ключи сохраняются.
use IterTools\Stream;
$rows = ['row 1', 'row 2', 'row 3', 'TOTAL'];
$result = Stream::of($rows)
->dropLast(1)
->toArray();
// row 1, row 2, row 3
Drop While
Пропускает элементы из потока, пока предикат возвращает истину.
$stream->dropWhile(callable $predicate): Stream
После того как предикат впервые вернул false, все последующие элементы попадают в выборку.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5]
$result = Stream::of($input)
->dropWhile(fn ($value) => $value < 3)
->toArray();
// 3, 4, 5
Enumerate
Итерирует пары [индекс, значение].
$stream->enumerate(int $start = 0): Stream
- Индекс генерируется последовательно начиная с
$start, независимо от ключей исходной коллекции. - Допускается отрицательное значение
$start.
use IterTools\Stream;
$seasons = ['spring', 'summer', 'autumn', 'winter'];
$result = Stream::of($seasons)
->enumerate()
->toArray();
// [[0, 'spring'], [1, 'summer'], [2, 'autumn'], [3, 'winter']]
Filter
Возвращает из потока только те элементы, для которых предикат возвращает истину.
$stream->filter(callable $predicate): Stream
По умолчанию (если не передан) предикат приводит элементы коллекции к bool.
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($input)
->filter(fn ($value) => $value > 0)
->toArray();
// 1, 2, 3
Filter True
Возвращает из потока только истинные элементы. Истинность определяется предикатом.
$stream->filterTrue(?callable $predicate = null): Stream
По умолчанию (если не передан) предикат приводит элементы коллекции к bool.
use IterTools\Stream;
$input = [0, 1, 2, 3, 0, 4];
$result = Stream::of($input)
->filterTrue()
->toArray();
// 1, 2, 3, 4
Filter False
Возвращает из потока только ложные элементы. Истинность определяется предикатом.
$stream->filterFalse(?callable $predicate = null): Stream
По умолчанию (если не передан) предикат приводит элементы коллекции к bool.
use IterTools\Stream;
$input = [0, 1, 2, 3, 0, 4];
$result = Stream::of($input)
->filterFalse(fn ($value) => $value > 0)
->filterFalse()
->toArray();
// 0, 0
Filter Keys
Возвращает из потока только те элементы, для ключей которых предикат возвращает истину.
$stream->filterKeys(callable $filter): Stream
$olympics = [
2000 => 'Sydney',
2002 => 'Salt Lake City',
2004 => 'Athens',
2006 => 'Turin',
2008 => 'Beijing',
2010 => 'Vancouver',
2012 => 'London',
2014 => 'Sochi',
2016 => 'Rio de Janeiro',
2018 => 'Pyeongchang',
2020 => 'Tokyo',
2022 => 'Beijing',
];
$winterFilter = fn ($year) => $year % 4 === 2;
$result = Stream::of($olympics)
->filterKeys($winterFilter)
->toAssociativeArray();
}
// 2002 => Salt Lake City
// 2006 => Turin
// 2010 => Vancouver
// 2014 => Sochi
// 2018 => Pyeongchang
// 2022 => Beijing
Filter With Keys
Фильтрует поток, передавая в предикат и значение, и ключ.
Оставляет элементы, для которых предикат — вызываемый как $predicate($value, $key) — возвращает истину (приводится к (bool)). Ключи сохраняются.
$stream->filterWithKeys(callable $predicate): Stream
$inventory = ['apples' => 5, 'bananas' => 0, 'avocados' => 3, 'cherries' => 0];
$inStockStartingWithA = fn ($count, $name) => $count > 0 && \str_starts_with($name, 'a');
$result = Stream::of($inventory)
->filterWithKeys($inStockStartingWithA)
->toAssociativeArray();
// ['apples' => 5, 'avocados' => 3]
Flat Map
Отображение коллекции из потока с уплощением результата на 1 уровень вложенности.
$stream->flatMap(callable $mapper): Stream
$data = [1, 2, 3, 4, 5];
$mapper fn ($item) => ($item % 2 === 0) ? [$item, $item] : $item;
$result = Stream::of($data)
->flatMap($mapper)
->toArray();
// [1, 2, 2, 3, 4, 4, 5]
Flat Map With Keys
Отображение коллекции из потока функцией, учитывающей ключи, с последующим уплощением результата на 1 уровень.
Функция вызывается как $func($value, $key, callable $self). Третий аргумент — сама функция, что позволяет рекурсивно уплощать вложенные коллекции. Внешние и внутренние ключи отбрасываются — результат отдаётся с автоматически сгенерированными последовательными числовыми ключами.
$stream->flatMapWithKeys(callable $func): Stream
$data = ['a' => 1, 'b' => 2, 'c' => 3];
$func = fn ($value, $key) => [$key, $value];
$result = Stream::of($data)
->flatMapWithKeys($func)
->toArray();
// ['a', 1, 'b', 2, 'c', 3]
Flatten
Многоуровневое уплощение коллекции из потока.
$stream->flatten(int $dimensions = 1): Stream
$data = [1, [2, 3], [4, 5]];
$result = Stream::of($data)
->flatten($mapper)
->toArray();
// [1, 2, 3, 4, 5]
Frequencies
Абсолютная частота распределения элементов потока.
$stream->frequencies(bool $strict = true): Stream
use IterTools\Stream;
$grades = ['A', 'A', 'B', 'B', 'B', 'C'];
$result = Stream::of($grades)
->frequencies()
->toAssociativeArray();
// ['A' => 2, 'B' => 3, 'C' => 1]
Frequencies By
Частота распределения элементов потока, сгруппированных по значению, которое возвращает функция-ключ.
$stream->frequenciesBy(callable $keyFunc, bool $strict = true): Stream
Функция-ключ должна возвращать int или string; при любом другом типе возвращаемого значения при обходе потока выбрасывается \TypeError.
use IterTools\Stream;
$words = ['apple', 'pear', 'banana', 'kiwi'];
$result = Stream::of($words)
->frequenciesBy(fn ($word) => \strlen($word))
->toAssociativeArray();
// [5 => 1, 4 => 2, 6 => 1]
Group By
Группирует элементы из потока по заданному правилу.
$stream->groupBy(callable $groupKeyFunction): Stream
Функция $groupKeyFunction должна возвращать общий ключ для элементов группы.
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($input)
->groupBy(fn ($item) => $item > 0 ? 'positive' : 'negative');
foreach ($result as $group => $item) {
// 'positive' => [1, 2, 3], 'negative' => [-1, -2, -3]
}
Infinite Cycle
Бесконечно зацикливает перебор элементов потока.
$stream->infiniteCycle(): Stream
use IterTools\Stream;
$input = [1, 2, 3];
$result = Stream::of($input)
->infiniteCycle()
->print();
// 1, 2, 3, 1, 2, 3, ...
Intersection With
Пересечение хранимой в потоке коллекции с другими переданными коллекциями.
$stream->intersectionWith(iterable ...$iterables): Stream
use IterTools\Stream;
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
$numerics = ['1', '2', 3, 4, 5, 6, 7, '8', '9'];
$oddNumbers = [1, 3, 5, 7, 9, 11];
$stream = Stream::of($numbers)
->intersectionWith($numerics, $oddNumbers)
->toArray();
// 3, 5, 7
Intersection Coercive With
Пересечение хранимой в потоке коллекции с другими переданными коллекциями в режиме приведения типов.
$stream->intersectionCoerciveWith(iterable ...$iterables): Stream
use IterTools\Stream;
$languages = ['php', 'python', 'c++', 'java', 'c#', 'javascript', 'typescript'];
$scriptLanguages = ['php', 'python', 'javascript', 'typescript'];
$supportsInterfaces = ['php', 'java', 'c#', 'typescript'];
$stream = Stream::of($languages)
->intersectionCoerciveWith($scriptLanguages, $supportsInterfaces)
->toArray();
// 'php', 'typescript'
Intersperse
Возвращает поток, в котором между последовательными элементами вставлен разделитель.
$stream->intersperse(mixed $separator): Stream
- Разделитель не выдаётся ни перед первым элементом, ни после последнего.
- Разделитель выдаётся как есть: массивы не разворачиваются, объекты сохраняют идентичность.
- Ключи исходной коллекции отбрасываются — на выходе список с последовательными целочисленными ключами.
use IterTools\Stream;
$flow = '';
foreach (Stream::of(['fetch', 'parse', 'validate', 'persist'])->intersperse(' -> ') as $part) {
$flow .= $part;
}
// 'fetch -> parse -> validate -> persist'
use IterTools\Stream;
$row = '';
foreach (Stream::of(['name', 'email', 'role'])->intersperse(',') as $part) {
$row .= $part;
}
// 'name,email,role'
См. также Single::intersperse.
Limit
Ограничивает итерирование элементов из потока заданным максимальным числом итераций.
Останавливает процесс итерирования, когда число итераций достигает $limit.
Ленивая операция: вышестоящий поток никогда не продвигается дальше тех элементов, которые были возвращены. При $limit, равном 0, вышестоящий поток не затрагивается вовсе.
$stream->limit(int $limit): Stream
Use IterTools\Single;
$matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections'];
$limit = 1;
$goodMovies = Stream::of($matrixMovies)
->limit($limit)
->toArray();
// 'The Matrix' (and nothing else)
Map
Отображение хранимой в потоке коллекции с использованием callback-функции.
$stream->map(callable $function): Stream
use IterTools\Stream;
$grades = [100, 95, 98, 89, 100];
$result = Stream::of($grades)
->map(fn ($grade) => $grade === 100 ? 'A' : 'F')
->toArray();
// A, F, F, F, A
Map With Keys
Отображение хранимой в потоке коллекции функцией, в которую передаются и значение, и ключ.
Функция вызывается как $func($value, $key). Преобразованное значение отдаётся с сохранением исходного ключа.
$stream->mapWithKeys(callable $func): Stream
use IterTools\Stream;
$prices = ['apple' => 1.5, 'banana' => 0.75, 'cherry' => 3.0];
$result = Stream::of($prices)
->mapWithKeys(fn ($price, $name) => "$name: \$$price")
->toAssociativeArray();
// ['apple' => 'apple: \$1.5', 'banana' => 'banana: \$0.75', 'cherry' => 'cherry: \$3']
Map Spread
Возвращает поток, где к каждому элементу применяется функция, при этом элемент распаковывается как позиционные аргументы функции.
$stream->mapSpread(callable $function): Stream
- Каждый элемент потока сам должен быть итерируемым; его значения передаются в
$functionпозиционно через splat-оператор. - Внутренние ключи отбрасываются — значения передаются позиционно, даже если внутренний элемент является ассоциативным массивом.
- Внешние ключи сохраняются (как и в
Stream::map). - Бросает
\InvalidArgumentException, если какой-либо внутренний элемент не является итерируемым.
use IterTools\Stream;
$result = Stream::of([[1, 2], [3, 4], [5, 6]])
->mapSpread(fn ($a, $b) => $a + $b)
->toArray();
// [3, 7, 11]
use IterTools\Stream;
$names = ['Alice', 'Bob', 'Carol'];
$scores = [92, 87, 95];
$result = Stream::of($names)
->zipWith($scores)
->mapSpread(fn (string $name, int $score) => "{$name}: {$score}")
->toArray();
// ['Alice: 92', 'Bob: 87', 'Carol: 95']
См. также Single::mapSpread.
Pairwise
Итерирует элементы из потока попарно (с наложением).
$stream->pairwise(): Stream
Итоговый поток окажется пустым, если исходный содержит меньше 2-х элементов.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$stream = Stream::of($input)
->pairwise()
->toArray();
// [1, 2], [2, 3], [3, 4], [4, 5]
Partial Intersection With
Частичное пересечение хранимой в потоке коллекции с другими переданными коллекциями.
$stream->partialIntersectionWith(int $minIntersectionCount, iterable ...$iterables): Stream
use IterTools\Stream;
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
$numerics = ['1', '2', 3, 4, 5, 6, 7, '8', '9'];
$oddNumbers = [1, 3, 5, 7, 9, 11];
$stream = Stream::of($numbers)
->partialIntersectionWith($numerics, $oddNumbers)
->toArray();
// 1, 3, 4, 5, 6, 7, 9
Partial Intersection Coercive With
Частичное пересечение хранимой в потоке коллекции с другими переданными коллекциями, вычисляемое в режиме приведения типов.
$stream->partialIntersectionCoerciveWith(int $minIntersectionCount, iterable ...$iterables): Stream
use IterTools\Stream;
$languages = ['php', 'python', 'c++', 'java', 'c#', 'javascript', 'typescript'];
$scriptLanguages = ['php', 'python', 'javascript', 'typescript'];
$supportsInterfaces = ['php', 'java', 'c#', 'typescript'];
$stream = Stream::of($languages)
->partialIntersectionCoerciveWith(2, $scriptLanguages, $supportsInterfaces)
->toArray();
// 'php', 'python', 'java', 'typescript', 'c#', 'javascript'
Reindex
Переиндексирует key-value коллекцию из потока, используя функцию-индексатор.
$stream->reindex(callable $indexer): Stream
use IterTools\Stream;
$data = [
[
'title' => 'Star Wars: Episode IV – A New Hope',
'episode' => 'IV',
'year' => 1977,
],
[
'title' => 'Star Wars: Episode V – The Empire Strikes Back',
'episode' => 'V',
'year' => 1980,
],
[
'title' => 'Star Wars: Episode VI – Return of the Jedi',
'episode' => 'VI',
'year' => 1983,
],
];
$reindexFunc = fn (array $swFilm) => $swFilm['episode'];
$reindexResult = Stream::of($data)
->reindex($reindexFunc)
->toAssociativeArray();
// [
// 'IV' => [
// 'title' => 'Star Wars: Episode IV – A New Hope',
// 'episode' => 'IV',
// 'year' => 1977,
// ],
// 'V' => [
// 'title' => 'Star Wars: Episode V – The Empire Strikes Back',
// 'episode' => 'V',
// 'year' => 1980,
// ],
// 'VI' => [
// 'title' => 'Star Wars: Episode VI – Return of the Jedi',
// 'episode' => 'VI',
// 'year' => 1983,
// ],
// ]
Relative Frequencies
Относительная частота распределения элементов потока.
$stream->relativeFrequencies(bool $strict = true): Stream
use IterTools\Stream;
$grades = ['A', 'A', 'B', 'B', 'B', 'C'];
$result = Stream::of($grades)
->relativeFrequencies()
->toAssociativeArray();
// A => 0.33, B => 0.5, C => 0.166
Relative Frequencies By
Относительная частота распределения элементов потока, сгруппированных по значению, которое возвращает функция-ключ.
$stream->relativeFrequenciesBy(callable $keyFunc, bool $strict = true): Stream
Функция-ключ должна возвращать int или string; при любом другом типе возвращаемого значения при обходе потока выбрасывается \TypeError.
use IterTools\Stream;
$words = ['apple', 'pear', 'kiwi', 'plum'];
$result = Stream::of($words)
->relativeFrequenciesBy(fn ($word) => \strlen($word))
->toAssociativeArray();
// [5 => 0.25, 4 => 0.75]
Reverse
Итерирует коллекцию из потока в обратном порядке.
$stream->reverse(): Stream
use IterTools\Stream;
$words = ['are', 'you', 'as', 'bored', 'as', 'I', 'am'];
$reversed = Stream::of($words)
->reverse()
->toString(' ');
// am I as bored as you are
Round Robin With
Поочерёдно отдаёт элементы из потока и заданных коллекций, чередуя источники.
$stream->roundRobinWith(iterable ...$iterables): Stream
В каждом раунде берётся по одному элементу из каждого источника, в котором ещё есть значения;
исчерпавшийся источник пропускается на последующих раундах. Итерирование завершается, когда
исчерпаны все источники. В отличие от zipWith, элементы возвращаются по одному, а не в виде кортежей.
Ключи источников отбрасываются; результат имеет последовательные целочисленные ключи.
use IterTools\Stream;
$result = Stream::of(['A', 'B', 'C'])
->roundRobinWith(['D', 'E'], ['F', 'G', 'H'])
->toArray();
// ['A', 'D', 'F', 'B', 'E', 'G', 'C', 'H']
Round-robin-планирование позволяет равномерно вычерпывать задачи из очередей разной длины:
$workerOne = ['task-1', 'task-4', 'task-7'];
$workerTwo = ['task-2', 'task-5'];
$workerThree = ['task-3', 'task-6', 'task-8', 'task-9'];
$schedule = Stream::of($workerOne)
->roundRobinWith($workerTwo, $workerThree)
->toArray();
// ['task-1', 'task-2', 'task-3', 'task-4', 'task-5', 'task-6', 'task-7', 'task-8', 'task-9']
См. также Multi::roundRobin.
Running Average
Накапливает среднее арифметическое элементов из потока в процессе итерирования.
$stream->runningAverage(int|float|null $initialValue = null): Stream
use IterTools\Stream;
$input = [1, 3, 5];
$result = Stream::of($input)
->runningAverage();
foreach ($result as $item) {
// 1, 2, 3
}
Running Difference
Накапливает разность элементов из потока в процессе итерирования.
$stream->runningDifference(int|float|null $initialValue = null): Stream
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($input)
->runningDifference()
->toArray();
// -1, -3, -6, -10, -15
Running Max
Возвращает поток, ищущий максимальный элемент из исходного потока в процессе итерирования.
$stream->runningMax(int|float|null $initialValue = null): Stream
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($input)
->runningMax()
->toArray();
// 1, 1, 2, 2, 3, 3
Running Min
Возвращает поток, ищущий минимальный элемент из исходного потока в процессе итерирования.
$stream->runningMin(int|float|null $initialValue = null): Stream
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($input)
->runningMin()
->toArray();
// 1, -1, -1, -2, -2, -3
Running Product
Возвращает поток, накапливающий произведение элементов из исходного потока в процессе итерирования.
$stream->runningProduct(int|float|null $initialValue = null): Stream
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($input)
->runningProduct()
->toArray();
// 1, 2, 6, 24, 120
Running Total
Возвращает поток, накапливающий сумму элементов из исходного потока в процессе итерирования.
$stream->runningTotal(int|float|null $initialValue = null): Stream
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($input)
->runningTotal()
->toArray();
// 1, 3, 6, 10, 15
Skip
Пропускает n элементов из потока и опциональным смещением.
$stream->skip(int $count, int $offset = 0): Stream
use IterTools\Stream;
$movies = [
'The Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith',
'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi',
'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'
];
$onlyTheBest = Stream::of($movies)
->skip(3)
->skip(3, 3)
->toArray();
// 'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi'
Slice
Выделяет подвыборку коллекции из потока.
Ленивая операция: вышестоящий поток никогда не продвигается дальше последнего возвращённого элемента. При $count, равном 0, вышестоящий поток не затрагивается вовсе. Элементы, пропускаемые из-за $start или $step, всё же должны быть вычитаны, чтобы быть пропущенными.
$stream->slice(int $start = 0, int $count = null, int $step = 1)
use IterTools\Stream;
$olympics = [1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2018, 2020, 2022];
$summerOlympics = Stream::of($olympics)
->slice(0, 8, 2)
->toArray();
// [1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020]
Sort
Сортирует хранимую в потоке коллекцию.
$stream->sort(callable $comparator = null)
Если $comparator не передан, элементы хранимой коллекции должны быть сравнимы.
use IterTools\Stream;
$input = [3, 4, 5, 9, 8, 7, 1, 6, 2];
$result = Stream::of($input)
->sort()
->toArray();
// 1, 2, 3, 4, 5, 6, 7, 8, 9
Sort By
Сортирует хранимую в потоке коллекцию по ключу, извлечённому из каждого элемента (преобразование Шварца).
$stream->sortBy(callable $keyFn)
Функция извлечения ключа вызывается ровно один раз для каждого элемента. Исходные ключи отбрасываются. Сортировка устойчивая: элементы с равными ключами сохраняют исходный относительный порядок.
См. также Sort::sortBy().
use IterTools\Stream;
$words = ['banana', 'fig', 'cherry', 'apple'];
$result = Stream::of($words)
->sortBy(fn (string $s) => \strlen($s))
->toArray();
// ['fig', 'apple', 'banana', 'cherry']
use IterTools\Stream;
$people = [
(object)['name' => 'Alice', 'age' => 30],
(object)['name' => 'Bob', 'age' => 20],
(object)['name' => 'Carol', 'age' => 40],
];
$names = Stream::of($people)
->sortBy(fn ($p) => $p->age)
->map(fn ($p) => $p->name)
->toArray();
// ['Bob', 'Alice', 'Carol']
Asort By
Сортирует хранимую в потоке коллекцию по ключу, извлечённому из каждого элемента (преобразование Шварца), с сохранением ключей.
$stream->asortBy(callable $keyFn)
Функция извлечения ключа вызывается ровно один раз для каждого элемента. Исходные ключи сохраняются. Сортировка устойчивая: элементы с равными ключами сохраняют исходный относительный порядок.
См. также Sort::asortBy().
use IterTools\Stream;
$scores = [
'Alice' => 87,
'Bob' => 92,
'Carol' => 75,
];
$result = Stream::of($scores)
->asortBy(fn (int $score) => $score)
->toAssociativeArray();
// ['Carol' => 75, 'Alice' => 87, 'Bob' => 92]
use IterTools\Stream;
$people = [
'alice' => (object)['age' => 30],
'bob' => (object)['age' => 20],
'carol' => (object)['age' => 40],
];
$result = Stream::of($people)
->asortBy(fn ($p) => $p->age)
->toAssociativeArray();
// ['bob' => (object)['age' => 20], 'alice' => (object)['age' => 30], 'carol' => (object)['age' => 40]]
Largest
Сводит поток к n наибольшим элементам (порядок убывания).
$stream->largest(int $n, callable $keyFn = null)
Использует ограниченную кучу размера n — полная сортировка потока не выполняется.
Устойчивая при равных ключах; пропускает NaN-ключи; бросает
\InvalidArgumentException для отрицательного $n.
См. также Sort::largest().
use IterTools\Stream;
$data = [3, 1, 4, 1, 5, 9, 2, 6];
$result = Stream::of($data)
->largest(3)
->toArray();
// [9, 6, 5]
use IterTools\Stream;
$leaderboard = [
(object)['name' => 'Alice', 'score' => 87],
(object)['name' => 'Bob', 'score' => 92],
(object)['name' => 'Carol', 'score' => 75],
(object)['name' => 'Dave', 'score' => 95],
(object)['name' => 'Eve', 'score' => 90],
];
$result = Stream::of($leaderboard)
->largest(3, fn ($p) => $p->score)
->map(fn ($p) => $p->name)
->toArray();
// ['Dave', 'Bob', 'Eve']
Smallest
Сводит поток к n наименьшим элементам (порядок возрастания).
$stream->smallest(int $n, callable $keyFn = null)
Использует ограниченную кучу размера n — полная сортировка потока не выполняется.
Устойчивая при равных ключах; пропускает NaN-ключи; бросает
\InvalidArgumentException для отрицательного $n.
См. также Sort::smallest().
use IterTools\Stream;
$data = [3, 1, 4, 1, 5, 9, 2, 6];
$result = Stream::of($data)
->smallest(3)
->toArray();
// [1, 1, 2]
use IterTools\Stream;
$requests = [
(object)['id' => 'r1', 'durationMs' => 120],
(object)['id' => 'r2', 'durationMs' => 50],
(object)['id' => 'r3', 'durationMs' => 200],
(object)['id' => 'r4', 'durationMs' => 80],
(object)['id' => 'r5', 'durationMs' => 65],
];
$result = Stream::of($requests)
->smallest(3, fn ($r) => $r->durationMs)
->map(fn ($r) => $r->id)
->toArray();
// ['r2', 'r5', 'r4']
Difference With
Возвращает поток, содержащий разность исходного потока с заданным набором коллекций. Элементы из исходного потока, не входящие ни в одну из заданных коллекций.
$stream->differenceWith(iterable ...$iterables): Stream
Если хотя бы в одной коллекции или в потоке встречаются повторяющиеся элементы, работают правила получения разности для мультимножеств.
use IterTools\Stream;
$a = [1, 2, 3, 4, 7];
$b = [2, 3, 5, 8];
$c = [1, 6, 9];
$stream = Stream::of($a)
->differenceWith($b, $c)
->toArray();
// 4, 7
Difference Coercive With
Возвращает поток, содержащий разность исходного потока с заданным набором коллекций, полученную в режиме приведения типов.
$stream->differenceCoerciveWith(iterable ...$iterables): Stream
Если хотя бы в одной коллекции или в потоке встречаются повторяющиеся элементы, работают правила получения разности для мультимножеств.
use IterTools\Stream;
$a = [1, 2, 3, 4, 7];
$b = ['1', 2, 3, 5, 8];
$stream = Stream::of($a)
->differenceCoerciveWith($b)
->toArray();
// 4, 7
Symmetric difference With
Возвращает поток, содержащий симметрическую разность исходного потока с заданным набором коллекций.
$stream->symmetricDifferenceWith(iterable ...$iterables): Stream
Если хотя бы в одной коллекции или в потоке встречаются повторяющиеся элементы, работают правила получения разности для мультимножеств.
use IterTools\Stream;
$a = [1, 2, 3, 4, 7];
$b = ['1', 2, 3, 5, 8];
$c = [1, 2, 3, 6, 9];
$stream = Stream::of($a)
->symmetricDifferenceWith($b, $c)
->toArray();
// '1', 4, 5, 6, 7, 8, 9
Symmetric difference Coercive With
Возвращает поток, содержащий симметрическую разность исходного потока с заданным набором коллекций, полученную в режиме приведения типов.
$stream->symmetricDifferenceCoerciveWith(iterable ...$iterables): Stream
Если хотя бы в одной коллекции или в потоке встречаются повторяющиеся элементы, работают правила получения разности для мультимножеств.
use IterTools\Stream;
$a = [1, 2, 3, 4, 7];
$b = ['1', 2, 3, 5, 8];
$c = [1, 2, 3, 6, 9];
$stream = Stream::of($a)
->symmetricDifferenceCoerciveWith($b, $c)
->toArray();
// 4, 5, 6, 7, 8, 9
Take Last
Перебирает последние $count элементов потока.
$stream->takeLast(int $count): Stream
Ленивый, но ограниченный: в памяти удерживается только кольцевой буфер размера $count. Если $count равен 0, не возвращается ничего; если $count больше длины потока, возвращаются все элементы. Ключи сохраняются.
use IterTools\Stream;
$logLines = ['line 1', 'line 2', 'line 3', 'line 4', 'line 5'];
$result = Stream::of($logLines)
->takeLast(2)
->toArray();
// line 4, line 5
Take While
Оставляет элементы в потоке, пока предикат возвращает истину.
$stream->takeWhile(callable $predicate): Stream
- Останавливает процесс итерации, как только предикат впервые вернет ложь.
- По умолчанию (если не передан) предикат приводит элементы коллекции к
bool.
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($input)
->takeWhile(fn ($value) => abs($value) < 3);
foreach ($result as $item) {
// 1, -1, 2, -2
}
Union With
Возвращает поток с объединением хранимой коллекции с другими поданными на вход коллекциями.
$stream->unionWith(iterable ...$iterables): Stream
Если хотя бы в одной коллекции встречаются повторяющиеся элементы, работают правила объединения мультимножеств.
use IterTools\Stream;
$input = [1, 2, 3];
$stream = Stream::of($input)
->unionWith([3, 4, 5, 6])
->toArray();
// [1, 2, 3, 4, 5, 6]
Union Coercive With
Возвращает поток с объединением хранимой коллекции с другими поданными на вход коллекциями в режиме приведения типов.
$stream->unionCoerciveWith(iterable ...$iterables): Stream
Если хотя бы в одной коллекции встречаются повторяющиеся элементы, работают правила объединения мультимножеств.
use IterTools\Stream;
$input = [1, 2, 3];
$stream = Stream::of($input)
->unionCoerciveWith(['3', 4, 5, 6])
->toArray();
// [1, 2, 3, 4, 5, 6]
Unzip
Рассматривает сам поток как последовательность строк и транспонирует их в столбцы — обратная операция к zip.
$stream->unzip(): Stream
Возвращает по одному массиву на каждый столбец, до ширины самой короткой строки. Внешний поток и все строки полностью потребляются при первом обращении к unzip-потоку: столбец 0 не может быть отдан, пока не известны первые ячейки всех строк.
use IterTools\Stream;
$pairs = [[1, 'a'], [2, 'b'], [3, 'c']];
$columns = Stream::of($pairs)
->unzip()
->toArray();
// [[1, 2, 3], ['a', 'b', 'c']]
Разделение событий вида (timestamp, value) на два параллельных ряда:
use IterTools\Stream;
$events = [
[1700000000, 12.5],
[1700000060, 13.1],
[1700000120, 12.9],
];
[$timestamps, $values] = Stream::of($events)
->unzip()
->toArray();
// $timestamps === [1700000000, 1700000060, 1700000120]
// $values === [12.5, 13.1, 12.9]
Zip
Рассматривает сам поток как последовательность итерируемых коллекций и транспонирует их по столбцам.
$stream->zip(): Stream
Для коллекций разной длины итерирование останавливается, когда самая короткая строка закончится. Аналогично идиоме Python zip(*rows).
use IterTools\Stream;
$rows = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
$stream = Stream::of($rows)
->zip()
->toArray();
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Хорошо сочетается с chunkwise() — разбейте плоский поток на группы и транспонируйте:
use IterTools\Stream;
$stream = Stream::of([1, 2, 3, 4, 5, 6])
->chunkwise(3)
->zip()
->toArray();
// [[1, 4], [2, 5], [3, 6]]
Естественно сочетается с toPartition() — составьте пары турнирной сетки, соединив верхнюю половину с перевёрнутой нижней (1 vs 8, 2 vs 7, 3 vs 6, 4 vs 5):
use IterTools\Stream;
[$topHalf, $bottomHalf] = Stream::of([1, 2, 3, 4, 5, 6, 7, 8])
->toPartition(fn (int $seed): bool => $seed <= 4);
$matchups = Stream::of([$topHalf, array_reverse($bottomHalf)])
->zip()
->toArray();
// [[1, 8], [2, 7], [3, 6], [4, 5]]
Транспонирование таблицы «строки → столбцы» — когда записи приходят построчно, но нужно получить каждое поле отдельной серией:
use IterTools\Stream;
$rows = [
['Alice', 30, 'NYC'],
['Bob', 25, 'LA'],
['Carol', 41, 'Austin'],
];
$columns = Stream::of($rows)
->zip()
->toArray();
// [['Alice', 'Bob', 'Carol'], [30, 25, 41], ['NYC', 'LA', 'Austin']]
Внешний поток должен быть конечным; он полностью потребляется при итерировании результата, до того как будет выдан первый кортеж. Внутренние строки после этого продвигаются лениво. Передача одного и того же экземпляра итератора более одного раза не поддерживается и может привести к неожиданному поведению.
Zip Longest
Рассматривает сам поток как последовательность итерируемых коллекций и транспонирует их по столбцам, продолжая до самой длинной строки.
$stream->zipLongest(): Stream
Для закончившихся строк выдаёт null на оставшихся итерациях. Аналогично идиоме Python zip_longest(*rows).
use IterTools\Stream;
$rows = [[1, 2, 3], [4, 5]];
$stream = Stream::of($rows)
->zipLongest()
->toArray();
// [[1, 4], [2, 5], [3, null]]
Сгруппировать помесячные показатели по годам при разной длине серий — короткие годы проявляются как null-пропуски вместо отбрасывания данных:
use IterTools\Stream;
$rainfallByYear = [
[3.2, 4.1, 5.0, 6.2], // 2022
[2.8, 3.9, 4.7], // 2023 — сбой датчика в середине года
[3.5, 4.3, 5.2, 6.8, 7.1], // 2024
];
$byMonth = Stream::of($rainfallByYear)
->zipLongest()
->toArray();
// [[3.2, 2.8, 3.5], [4.1, 3.9, 4.3], [5.0, 4.7, 5.2], [6.2, null, 6.8], [null, null, 7.1]]
Внешний поток должен быть конечным; он полностью потребляется при итерировании результата, до того как будет выдан первый кортеж. Внутренние строки после этого продвигаются лениво. Передача одного и того же экземпляра итератора более одного раза не поддерживается и может привести к неожиданному поведению.
Zip Filled
Рассматривает сам поток как последовательность итерируемых коллекций и транспонирует их по столбцам, продолжая до самой длинной строки и подставляя филлер для отсутствующих значений.
$stream->zipFilled(mixed $filler): Stream
Для закончившихся строк выдаёт значение $filler на оставшихся итерациях.
use IterTools\Stream;
$rows = [[1, 2, 3], [4, 5]];
$stream = Stream::of($rows)
->zipFilled('?')
->toArray();
// [[1, 4], [2, 5], [3, '?']]
Полезно, когда потребителю нужен числовой дефолт вместо null — например, квартальные продажи по командам, где недостающие кварталы должны считаться нулями при агрегации:
use IterTools\Stream;
$salesByTeam = [
[120, 150, 180, 210], // Команда A — полный год
[ 95, 110], // Команда B — подключена во втором полугодии
[140, 160, 175], // Команда C — Q4 ещё не закрыт
];
$byQuarter = Stream::of($salesByTeam)
->zipFilled(0)
->toArray();
// [[120, 95, 140], [150, 110, 160], [180, 0, 175], [210, 0, 0]]
Внешний поток должен быть конечным; он полностью потребляется при итерировании результата, до того как будет выдан первый кортеж. Внутренние строки после этого продвигаются лениво. Передача одного и того же экземпляра итератора более одного раза не поддерживается и может привести к неожиданному поведению.
Zip Equal
Рассматривает сам поток как последовательность итерируемых коллекций равной длины и транспонирует их по столбцам.
$stream->zipEqual(): Stream
Работает как Stream::zip(), но бросает \LengthException, если длины строк не равны (по крайней мере одна строка закончится раньше других). Используется, когда равные длины являются обязательным инвариантом.
use IterTools\Stream;
$rows = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
$stream = Stream::of($rows)
->zipEqual()
->toArray();
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Естественно подходит для CSV-подобных записей, где у каждой строки должно быть одинаковое число полей — транспонирование в столбцы обнаружит нарушение схемы как \LengthException вместо молчаливого усечения или дополнения:
use IterTools\Stream;
$records = [
['id', 'name', 'email'],
[1, 'Alice', 'alice@example.com'],
[2, 'Bob', 'bob@example.com'],
];
$byField = Stream::of($records)
->zipEqual()
->toArray();
// [['id', 1, 2], ['name', 'Alice', 'Bob'], ['email', 'alice@example.com', 'bob@example.com']]
Внешний поток должен быть конечным; он полностью потребляется при итерировании результата, до того как будет выдан первый кортеж. Внутренние строки после этого продвигаются лениво. Передача одного и того же экземпляра итератора более одного раза не поддерживается и может привести к неожиданному поведению.
Zip With
Параллельно итерирует элементы из потока вместе с элементами переданных коллекций, пока не закончится самый короткий итератор.
$stream->zipWith(iterable ...$iterables): Stream
- Создает итератор, который агрегирует данные из нескольких итераторов.
- Работает аналогично функции
zip()в Python. - Для коллекций разной длины продолжает процесс итерирования до момента, пока самая короткая коллекция не закончится.
use IterTools\Stream;
$input = [1, 2, 3];
$stream = Stream::of($input)
->zipWith([4, 5, 6])
->zipWith([7, 8, 9])
->toArray();
// [1, 4, 7], [2, 5, 8], [3, 6, 9]
Zip Filled With
Параллельно итерирует элементы из потока вместе с элементами переданных коллекций, пока не закончится самый длинный итератор.
Для закончившихся итераторов подставляет заданный филлер в кортеж значений итерации.
$stream->zipFilledWith(mixed $default, iterable ...$iterables): Stream
use IterTools\Stream;
$input = [1, 2, 3];
$stream = Stream::of($input)
->zipFilledWith('?', ['A', 'B']);
foreach ($stream as $zipped) {
// [1, A], [2, B], [3, ?]
}
Zip Longest With
Параллельно итерирует элементы из потока вместе с элементами переданных коллекций, пока не закончится самый длинный итератор.
$stream->zipLongestWith(iterable ...$iterables): Stream
- Создает итератор, который агрегирует данные из нескольких итераторов.
- Работает аналогично функции
zip_longest()в Python. - Для коллекций разной длины продолжает процесс итерирования до момента, пока самая длинная коллекция не закончится.
- Для коллекций разной длины отдает вместо элементов
nullдля коллекций, которые закончились.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($input)
->zipLongestWith([4, 5, 6])
->zipLongestWith([7, 8, 9, 10]);
foreach ($result as $item) {
// [1, 4, 7], [2, 5, 8], [3, 6, 9], [4, null, 10], [null, null, 5]
}
Zip Equal With
Параллельно итерирует элементы из потока вместе с элементами переданных коллекций (все коллекции должны быть одной длины).
$stream->zipEqualWith(iterable ...$iterables): Stream
Работает как Multi::zip(), но бросает \LengthException, когда выясняется, что длины коллекций разные
(когда закончился самая короткая коллекция).
use IterTools\Stream;
$input = [1, 2, 3];
$result = Stream::of($input)
->zipEqualWith([4, 5, 6])
->zipEqualWith([7, 8, 9]);
foreach ($result as $item) {
// [1, 4, 7], [2, 5, 8], [3, 6, 9]
}
Append
Добавляет значения в конец потока.
$stream->append(mixed ...$values): Stream
- Для добавления целой коллекции используйте
chainWith. - Ключи результата переиндексируются последовательно по всему потоку.
- Пустой набор аргументов оставляет поток без изменений.
use IterTools\Stream;
$result = Stream::of([1, 2])->append(3, 4)->toArray();
// [1, 2, 3, 4]
Prepend
Добавляет значения в начало потока.
$stream->prepend(mixed ...$values): Stream
- Для добавления целой коллекции используйте
chainWith. - Ключи результата переиндексируются последовательно по всему потоку.
- Пустой набор аргументов оставляет поток без изменений.
use IterTools\Stream;
$result = Stream::of([3, 4])->prepend(1, 2)->toArray();
// [1, 2, 3, 4]
Split When
Разбивает поток на группы, начиная новую группу при каждом совпадении предиката.
$stream->splitWhen(callable $predicate): Stream
Совпавший элемент начинает следующую группу. Ключи исходной коллекции отбрасываются; внешний массив — последовательный, внутренние группы — list-массивы.
use IterTools\Stream;
$result = Stream::of([1, 2, 0, 3, 0, 4])
->splitWhen(fn ($x) => $x === 0)
->toArray();
// [[1, 2], [0, 3], [0, 4]]
Group Adjacent By
Группирует подряд идущие элементы, имеющие одинаковый ключ, возвращаемый функцией $keyFn.
$stream->groupAdjacentBy(callable $keyFn): Stream
Отдаёт пары [ключ_группы, list<значение>] последовательно. Повторяющиеся ключи, встречающиеся в разных подряд идущих сериях, дают отдельные группы.
use IterTools\Stream;
$result = Stream::of([1, 1, 2, 2, 1])
->groupAdjacentBy(fn ($x) => $x)
->toArray();
// [[1, [1, 1]], [2, [2, 2]], [1, [1]]]
Pad Left
Дополняет поток слева до длины не менее $length.
$stream->padLeft(int $length, mixed $fill): Stream
- Если поток уже имеет длину
$lengthили больше, все элементы проходят без изменений. - Ключи исходной коллекции отбрасываются; ключи результата — последовательные, начиная с 0.
- Бросает
\InvalidArgumentException, если$lengthотрицателен.
use IterTools\Stream;
$result = Stream::of([1, 2, 3])->padLeft(5, 0)->toArray();
// [0, 0, 1, 2, 3]
Pad Right
Дополняет поток справа до длины не менее $length.
$stream->padRight(int $length, mixed $fill): Stream
- Если поток уже имеет длину
$lengthили больше, все элементы проходят без изменений. - Ключи исходной коллекции отбрасываются; ключи результата — последовательные, начиная с 0.
- Бросает
\InvalidArgumentException, если$lengthотрицателен.
use IterTools\Stream;
$result = Stream::of([1, 2, 3])->padRight(5, 0)->toArray();
// [1, 2, 3, 0, 0]
Duplicates
Отдаёт каждое дублирующееся значение по одному разу — в момент его второго появления.
$stream->duplicates(bool $strict = true): Stream
use IterTools\Stream;
$result = Stream::of([1, 2, 1, 1, 2, 3])->duplicates()->toArray();
// [1, 2]
Duplicates By
Отдаёт каждое значение, чей извлечённый ключ совпадает с уже встречавшимся, по одному разу — в момент второго появления такого ключа.
$stream->duplicatesBy(callable $keyFn): Stream
use IterTools\Stream;
$users = [
['id' => 1, 'name' => 'Alice'],
['id' => 2, 'name' => 'Bob'],
['id' => 1, 'name' => 'Alicia'],
];
$result = Stream::of($users)
->duplicatesBy(fn ($u) => $u['id'])
->toArray();
// [['id' => 1, 'name' => 'Alicia']]
Shuffle
Рандомизирует порядок элементов потока.
$stream->shuffle(?\Random\Engine $engine = null): Stream
- Материализует поток.
- Ключи исходной коллекции отбрасываются; ключи результата — последовательные, начиная с 0.
use IterTools\Stream;
$result = Stream::of([1, 2, 3, 4, 5])->shuffle()->toArray();
// например: [3, 1, 5, 4, 2]
Sample
Возвращает выборку из $size элементов потока без повторений.
$stream->sample(int $size, ?\Random\Engine $engine = null): Stream
- Материализует поток. Ключи результата — последовательные, начиная с 0.
- Бросает
\InvalidArgumentException, если$sizeотрицателен. - Бросает
\LengthException, если$sizeпревышает длину потока.
use IterTools\Stream;
$result = Stream::of([1, 2, 3, 4, 5])->sample(3)->toArray();
// например: [4, 1, 5]
Reservoir Sample
Возвращает равномерно случайную выборку до $size элементов потока за один проход (алгоритм R).
$stream->reservoirSample(int $size, ?\Random\Engine $engine = null): Stream
- В отличие от ленивого
sample, эта операция энергичная: она потребляет вышестоящий поток немедленно в момент вызова и связывает полученный массив как новый источник потока. - Когда
$size >=длины потока, весь поток возвращается в исходном порядке без единой случайной выборки. Ключи результата — последовательные, начиная с 0. - Бросает
\InvalidArgumentException, если$sizeотрицателен.
use IterTools\Stream;
$result = Stream::of([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
->reservoirSample(3)
->toArray();
// например: [2, 7, 9]
Windowed
Итерирует скользящие окна из $size элементов потока, сдвигаясь на $step элементов между окнами.
$stream->windowed(int $size, int $step = 1, bool $partial = false): Stream
- Каждое окно — это list-массив с индексами от 0; ключи исходной коллекции отбрасываются. Поддерживает окна с пропусками (
$step > $size). - При
1 <= $step <= $sizeэквивалентноchunkwiseOverlap($size, $size - $step, includeIncompleteTail: $partial)(см. Chunkwise Overlap). $partialуправляет тем, отдаётся ли последнее неполное окно. Обратите внимание: по умолчаниюfalse— противоположно значению по умолчаниюtrueуincludeIncompleteTailвchunkwiseOverlap.- Бросает
\InvalidArgumentException, если$size < 1или$step < 1.
use IterTools\Stream;
$result = Stream::of([1, 2, 3, 4, 5])
->windowed(3)
->toArray();
// [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
With First
Сопоставляет каждому элементу потока булев флаг, отмечающий, является ли он первым элементом.
$stream->withFirst(): Stream
Отдаёт кортежи [bool $isFirst, mixed $value]. Ключи исходной коллекции отбрасываются; ключи результата — последовательные, начиная с 0.
use IterTools\Stream;
$result = Stream::of(['a', 'b', 'c'])
->withFirst()
->toArray();
// [[true, 'a'], [false, 'b'], [false, 'c']]
With Last
Сопоставляет каждому элементу потока булев флаг, отмечающий, является ли он последним элементом.
$stream->withLast(): Stream
Отдаёт кортежи [bool $isLast, mixed $value]. Ключи исходной коллекции отбрасываются; ключи результата — последовательные, начиная с 0.
use IterTools\Stream;
$result = Stream::of(['a', 'b', 'c'])
->withLast()
->toArray();
// [[false, 'a'], [false, 'b'], [true, 'c']]
With First And Last
Сопоставляет каждому элементу потока флаги, отмечающие, является ли он первым и/или последним элементом.
$stream->withFirstAndLast(): Stream
Отдаёт кортежи [bool $isFirst, bool $isLast, mixed $value]. Поток из одного элемента отдаёт один кортеж [true, true, $value]. Ключи исходной коллекции отбрасываются; ключи результата — последовательные, начиная с 0.
use IterTools\Stream;
$result = Stream::of(['a', 'b', 'c'])
->withFirstAndLast()
->toArray();
// [[true, false, 'a'], [false, false, 'b'], [false, true, 'c']]
Завершающие операции
Саммари о потоке
All Match
Возвращает истину, если для всех элементов из потока предикат возвращает истину.
$stream->allMatch(callable $predicate): bool
use IterTools\Summary;
$finalFantasyNumbers = [4, 5, 6];
$isOnSuperNintendo = fn ($ff) => $ff >= 4 && $ff <= 6;
$boolean = Stream::of($finalFantasyNumbers)
->allMatch($isOnSuperNintendo);
// true
All Unique
Возвращает истину, все элементы коллекции потока уникальны.
$stream->allUnique(bool $strict = true): bool
По умолчанию работает в режиме строгой типизации. Установите параметр $strict в false для работы в режиме приведения типов.
use IterTools\Summary;
$items = ['fingerprints', 'snowflakes', 'eyes', 'DNA']
$boolean = Stream::of($items)
->allUnique();
// true
Any Match
Возвращает истину, если хотя бы для одного элемента из потока предикат возвращает истину.
$stream->anyMatch(callable $predicate): bool
use IterTools\Summary;
$answers = ['fish', 'towel', 42, "don't panic"];
$isUltimateAnswer = fn ($a) => a == 42;
$boolean = Stream::of($answers)
->anyMatch($answers, $isUltimateAnswer);
// true
At Least N
Возвращает истину, если предикат возвращает истину как минимум для n элементов из потока.
- Предикат является необязательным аргументом.
- По умолчанию предикат приводит элементы коллекции к
bool. - Прерывает итерацию сразу после того, как количество совпадений достигнет n.
- При
n <= 0всегда возвращает истину.
$stream->atLeastN(int $n, callable $predicate = null): bool
use IterTools\Stream;
$grades = [45, 50, 61, 72, 85];
$isPassingGrade = fn ($grade) => $grade >= 70;
$boolean = Stream::of($grades)->atLeastN(2, $isPassingGrade);
// true
At Most N
Возвращает истину, если предикат возвращает истину не более чем для n элементов из потока.
- Предикат является необязательным аргументом.
- По умолчанию предикат приводит элементы коллекции к
bool. - Прерывает итерацию сразу после того, как количество совпадений превысит n.
- При
n < 0всегда возвращает ложь.
$stream->atMostN(int $n, callable $predicate = null): bool
use IterTools\Stream;
$attempts = [false, false, true, false];
$isFailure = fn ($attempt) => $attempt === false;
$boolean = Stream::of($attempts)->atMostN(3, $isFailure);
// true
Are Permutations With
Возвращает истину, если коллекция из потока и переданные коллекции являются перестановками друг друга.
$stream->arePermutationsWith(...$iterables): bool
use IterTools\Summary;
$rite = ['r', 'i', 't', 'e'];
$reit = ['r', 'e', 'i', 't'];
$tier = ['t', 'i', 'e', 'r'];
$tire = ['t', 'i', 'r', 'e'];
$trie = ['t', 'r', 'i', 'e'];
$boolean = Stream::of(['i', 't', 'e', 'r'])
->arePermutationsWith($rite, $reit, $tier, $tire, $trie);
// true
Are Permutations Coercive With
Возвращает истину, если коллекция из потока и переданные коллекции являются перестановками друг друга (в режиме приведения типов).
$stream->arePermutationsCoerciveWith(...$iterables): bool
use IterTools\Summary;
$set2 = [2.0, '1', 3];
$set3 = [3, 2, 1];
$boolean = Stream::of([1, 2.0, '3'])
->arePermutationsCoerciveWith($set2, $set3);
// true
Contains
Возвращает истину, если поток содержит искомое значение, при строгом сравнении типов.
$stream->contains(mixed $needle): bool
- Скаляры сравниваются строго по типу (
1не равно'1';0не равноfalse). - Для объектов совпадает только один и тот же экземпляр.
- Массивы сравниваются через
===. NaNникогда не совпадает сNaN.- Обрывает итерацию при первом совпадении.
use IterTools\Stream;
$primes = [2, 3, 5, 7, 11, 13];
$boolean = Stream::of($primes)->contains(7);
// true
$boolean = Stream::of($primes)->contains('7');
// false (строгое сравнение)
Contains Coercive
Возвращает истину, если поток содержит искомое значение, в режиме приведения типов.
$stream->containsCoercive(mixed $needle): bool
- Скаляры сравниваются нестрого по значению (
1совпадает с'1';0совпадает сfalse;'1e2'совпадает с100). - Объекты сравниваются по сериализованному значению (бросает
\InvalidArgumentException, если искомое значение или элемент потока не сериализуется). - Массивы сравниваются по сериализованному значению.
NaNсовпадает сNaN.- Обрывает итерацию при первом совпадении.
use IterTools\Stream;
$primes = [2, 3, 5, 7, 11, 13];
$boolean = Stream::of($primes)->containsCoercive('7');
// true (приведение типов)
Ends With
Возвращает истину, если поток заканчивается заданным суффиксом, при строгом сравнении типов.
- Сравнение значений идёт попарно; ключи игнорируются.
- Пустой суффикс возвращает истину без потребления потока.
- Поток должен быть конечным.
$stream->endsWith(iterable $suffix): bool
use IterTools\Stream;
$path = ['var', 'log', 'nginx', 'access.log'];
$boolean = Stream::of($path)->endsWith(['nginx', 'access.log']);
// true
$boolean = Stream::of($path)->endsWith(['error.log']);
// false
Ends With Coercive
Возвращает истину, если поток заканчивается заданным суффиксом, в режиме приведения типов.
- Сравнение значений идёт попарно; ключи игнорируются.
- Пустой суффикс возвращает истину без потребления потока.
- Поток должен быть конечным.
- Скаляры сравниваются нестрого по значению, объекты и массивы — по сериализованному значению,
NaNсовпадает сNaN. - Бросает
\InvalidArgumentException, если в процессе сравнения встретится несериализуемый объект.
$stream->endsWithCoercive(iterable $suffix): bool
use IterTools\Stream;
$digits = [1, 2, 3];
$boolean = Stream::of($digits)->endsWithCoercive(['2', '3']);
// true (приведение типов)
Exactly N
Возвращает истину, если в точности для n элементов из потока предикат возвращает истину.
- Предикат является необязательным аргументом.
- По умолчанию (если не передан) предикат приводит элементы коллекции к
bool.
$stream->exactlyN(int $n, callable $predicate = null): bool
use IterTools\Summary;
$twoTruthsAndALie = [true, true, false];
$n = 2;
$boolean = Stream::of($twoTruthsAndALie)->exactlyN($n);
// true
Is Empty
Возвращает истину, если коллекция потока пуста.
$stream->isEmpty(): bool
use IterTools\Summary;
$numbers = [0, 1, 2, 3, 4, 5];
$filterFunc = fn ($x) => $x > 10;
$boolean = Stream::($numbers)
->filter($filterFunc)
->isEmpty();
// true
Is Partitioned
Возвращает истину, если все истинные элементы коллекции из потока находятся в коллекции перед ложными (истинность определяет предикат).
- Возвращает истину для пустой коллекции и для коллекции с одним элементом.
- Если предикат не был передан, истинность элемента получается через приведение его значения к булевому типу.
$stream->isPartitioned(callable $predicate = null): bool
use IterTools\Summary;
$numbers = [0, 2, 4, 1, 3, 5];
$evensBeforeOdds = fn ($item) => $item % 2 === 0;
$boolean = Stream::($numbers)
->isPartitioned($evensBeforeOdds);
// true
Is Sorted
Возвращает истину, если коллекция элементов из потока отсортирована в прямом порядке, иначе — ложь.
$stream->isSorted(): bool
Элементы должны быть сравнимы.
Для пустой коллекции или коллекции из одного элемента всегда возвращает истину.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($input)
->isSorted();
// true
$input = [1, 2, 3, 2, 1];
$result = Stream::of($input)
->isSorted();
// false
Is Reversed
Возвращает истину, если коллекция элементов из потока отсортирована в обратном порядке, иначе — ложь.
$stream->isReversed(): bool
Элементы должны быть сравнимы.
Для пустой коллекции или коллекции из одного элемента всегда возвращает истину.
use IterTools\Stream;
$input = [5, 4, 3, 2, 1];
$result = Stream::of($input)
->isReversed();
// true
$input = [1, 2, 3, 2, 1];
$result = Stream::of($input)
->isReversed();
// false
Is Sorted By
Возвращает истину, если значения, вычисленные функцией-ключом, упорядочены по неубыванию (по возрастанию), иначе — ложь.
$stream->isSortedBy(callable $keyFunc): bool
Вычисленные значения должны быть сравнимы.
Для пустой коллекции или коллекции из одного элемента всегда возвращает истину.
use IterTools\Stream;
$people = [
(object)['name' => 'Alice', 'age' => 25],
(object)['name' => 'Bob', 'age' => 30],
(object)['name' => 'Carol', 'age' => 42],
];
$result = Stream::of($people)
->isSortedBy(fn ($person) => $person->age);
// true
Is Reversed By
Возвращает истину, если значения, вычисленные функцией-ключом, упорядочены по невозрастанию (по убыванию), иначе — ложь.
$stream->isReversedBy(callable $keyFunc): bool
Вычисленные значения должны быть сравнимы.
Для пустой коллекции или коллекции из одного элемента всегда возвращает истину.
use IterTools\Stream;
$people = [
(object)['name' => 'Carol', 'age' => 42],
(object)['name' => 'Bob', 'age' => 30],
(object)['name' => 'Alice', 'age' => 25],
];
$result = Stream::of($people)
->isReversedBy(fn ($person) => $person->age);
// true
None Match
Возвращает истину, если для всех элементов из потока предикат вернул ложь.
$stream->noneMatch(callable $predicate): bool
use IterTools\Summary;
$grades = [45, 50, 61, 0];
$isPassingGrade = fn ($grade) => $grade >= 70;
$boolean = Stream::of($grades)->noneMatch($isPassingGrade);
// true
Same With
Возвращает истину, если коллекция элементов из потока идентична переданным в аргументах коллекциям.
$stream->sameWith(iterable ...$iterables): bool
Если в метод не передать ни одной коллекции, он вернет истину.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($input)
->sameWith([1, 2, 3, 4, 5]);
// true
$result = Stream::of($input)
->sameWith([5, 4, 3, 2, 1]);
// false
Same Count With
Возвращает истину, если и коллекция элементов из потока, и все переданные коллекции имеют одинаковую длину.
$stream->sameCountWith(iterable ...$iterables): bool
Если в метод не передать ни одной коллекции, он вернет истину.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($input)
->sameCountWith([5, 4, 3, 2, 1]);
// true
$result = Stream::of($input)
->sameCountWith([1, 2, 3]);
// false
Starts With
Возвращает истину, если поток начинается с заданного префикса, при строгом сравнении типов.
- Сравнение значений идёт попарно; ключи игнорируются.
- Пустой префикс возвращает истину без потребления потока.
$stream->startsWith(iterable $prefix): bool
use IterTools\Stream;
$path = ['var', 'log', 'nginx', 'access.log'];
$boolean = Stream::of($path)->startsWith(['var', 'log']);
// true
$boolean = Stream::of($path)->startsWith(['etc']);
// false
Starts With Coercive
Возвращает истину, если поток начинается с заданного префикса, в режиме приведения типов.
- Сравнение значений идёт попарно; ключи игнорируются.
- Пустой префикс возвращает истину без потребления потока.
- Скаляры сравниваются нестрого по значению, объекты и массивы — по сериализованному значению,
NaNсовпадает сNaN. - Бросает
\InvalidArgumentException, если в процессе сравнения встретится несериализуемый объект.
$stream->startsWithCoercive(iterable $prefix): bool
use IterTools\Stream;
$digits = [1, 2, 3];
$boolean = Stream::of($digits)->startsWithCoercive(['1', '2']);
// true (приведение типов)
Редуцирование
To Average
Возвращает среднее арифметическое коллекции элементов из потока.
$stream->toAverage(): mixed
Для пустой коллекции вернет null.
use IterTools\Stream;
$input = [2, 4, 6, 8];
$result = Stream::of($iterable)
->toAverage();
// 5
To Count
Возвращает длину коллекции элементов из потока.
$stream->toCount(): mixed
use IterTools\Stream;
$input = [10, 20, 30, 40, 50];
$result = Stream::of($iterable)
->toCount();
// 5
To Count By
Сворачивает коллекцию элементов из потока в массив количеств, сгруппированных по значению, которое возвращает функция-ключ.
$stream->toCountBy(callable $keyFunc): array
Функция-ключ должна возвращать int или string; при любом другом типе возвращаемого значения выбрасывается \TypeError.
use IterTools\Stream;
$words = ['apple', 'pear', 'banana', 'kiwi', 'plum'];
$result = Stream::of($words)
->toCountBy(fn ($word) => \strlen($word));
// [5 => 1, 4 => 3, 6 => 1]
To First
Возвращает первый элемент из коллекции в потоке.
$stream->toFirst(): mixed
Бросает \LengthException если хранимая в потоке коллекция пуста.
use IterTools\Stream;
$input = [10, 20, 30];
$result = Stream::of($input)
->toFirst();
// 10
To First And Last
Возвращает первый и последний элементы из коллекции в потоке.
$stream->toFirstAndLast(): array{mixed, mixed}
Бросает \LengthException если хранимая в потоке коллекция пуста.
use IterTools\Stream;
$input = [10, 20, 30];
$result = Stream::of($input)
->toFirstAndLast();
// [10, 30]
To First Match
Возвращает первый элемент из коллекции в потоке, удовлетворяющий предикату.
$stream->toFirstMatch(callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Завершает обход на первом совпадении.
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Stream;
$numbers = [1, 3, 5, 6, 7, 8];
$result = Stream::of($numbers)
->toFirstMatch(fn (int $n) => $n % 2 === 0);
// 6
To First Match Index
Возвращает индекс (отсчёт от нуля) первого элемента в потоке, удовлетворяющего предикату.
$stream->toFirstMatchIndex(callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Завершает обход на первом совпадении.
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Stream;
$numbers = [10, 20, 30, 40];
$result = Stream::of($numbers)
->toFirstMatchIndex(fn (int $n) => $n > 25);
// 2
To First Match Key
Возвращает ключ исходной коллекции для первого элемента в потоке, удовлетворяющего предикату.
$stream->toFirstMatchKey(callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Завершает обход на первом совпадении.
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Stream;
$users = ['alice' => 12, 'bob' => 17, 'carol' => 22, 'dan' => 30];
$result = Stream::of($users)
->toFirstMatchKey(fn (int $age) => $age >= 18);
// 'carol'
To Last
Возвращает последний элемент из коллекции в потоке.
$stream->toLast(): mixed
Бросает \LengthException если хранимая в потоке коллекция пуста.
use IterTools\Stream;
$input = [10, 20, 30];
$result = Stream::of($input)
->toLast();
// 30
To Last Match
Возвращает последний элемент потока, удовлетворяющий предикату.
$stream->toLastMatch(callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Полностью потребляет коллекцию.
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Stream;
$numbers = [1, 3, 5, 6, 7, 8, 9];
$result = Stream::of($numbers)
->toLastMatch(fn (int $n) => $n % 2 === 0);
// 8
To Last Match Index
Возвращает индекс (отсчёт от нуля) последнего элемента потока, удовлетворяющего предикату.
$stream->toLastMatchIndex(callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Полностью потребляет коллекцию.
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Stream;
$numbers = [10, 20, 30, 40, 5];
$result = Stream::of($numbers)
->toLastMatchIndex(fn (int $n) => $n > 25);
// 3
To Last Match Key
Возвращает ключ исходной коллекции для последнего элемента потока, удовлетворяющего предикату.
$stream->toLastMatchKey(callable $predicate, mixed $default = null): mixed
- Результат предиката приводится к
boolчерез(bool). - Полностью потребляет коллекцию.
- Возвращает
$default(по умолчаниюnull), если совпадений нет.
use IterTools\Stream;
$users = ['alice' => 12, 'bob' => 17, 'carol' => 22, 'dan' => 30];
$result = Stream::of($users)
->toLastMatchKey(fn (int $age) => $age >= 18);
// 'dan'
To Max
Возвращает максимальный элемент коллекции из потока.
$stream->toMax(callable $compareBy = null): mixed
- Функция
$compareByдолжна возвращать сравнимое значение. - Если аргумент
$compareByне передан, элементы коллекции должны быть сравнимы. - Для пустой коллекции вернет
null.
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($iterable)
->toMax();
// 3
To Median
Возвращает медиану коллекции из потока.
$stream->toMedian(): int|float|null
- Для чётного количества элементов медиана равна среднему арифметическому двух средних значений; вычисление не переполняется, даже если сумма двух средних значений превышает
PHP_FLOAT_MAX, и не теряет точность, если их размах выходит за пределы целочисленного диапазона. Два одинаковых средних значения дают само это значение, включаяINF. - Для пустой коллекции вернет
null.
use IterTools\Stream;
$grades = [100, 90, 95, 85, 94];
$median = Stream::of($grades)
->toMedian();
// 94
To Min
Возвращает минимальный элемент коллекции из потока.
$stream->toMin(callable $compareBy = null): mixed
- Функция
$compareByдолжна возвращать сравнимое значение. - Если аргумент
$compareByне передан, элементы коллекции должны быть сравнимы. - Для пустой коллекции вернет
null.
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($iterable)
->toMin();
// -3
To Min Max
Возвращает минимальный и максимальный элементы коллекции из потока.
$stream->toMinMax(callable $compareBy = null): array
- Функция
$compareByдолжна возвращать сравнимое значение. - Если аргумент
$compareByне передан, элементы коллекции должны быть сравнимы. - Для пустой коллекции вернет
[null, null].
use IterTools\Stream;
$numbers = [1, 2, 3, -1, -2, -3];
[$min, $max] = Stream::of($numbers)
->toMinMax();
// [-3, 3]
To Mode
Возвращает список мод коллекции из потока (наиболее часто встречающихся значений).
$stream->toMode(): array
- Возвращает все значения с максимальной частотой в порядке первого появления.
- Для пустой коллекции возвращает пустой массив.
use IterTools\Stream;
$votes = ['red', 'blue', 'red', 'green', 'blue', 'red'];
$modes = Stream::of($votes)
->toMode();
// ['red']
To Nth
Возвращает n-й элемент потока.
$stream->toNth(int $position): mixed
Для пустой коллекции возвращает null.
use IterTools\Stream;
$lotrMovies = ['The Fellowship of the Ring', 'The Two Towers', 'The Return of the King'];
$result = Stream::of($lotrMovies)
->toNth(2);
// The Return of the King
To Only
Возвращает единственный элемент потока.
$stream->toOnly(): mixed
- Бросает
\LengthException, если поток пуст или содержит более одного элемента. - Удобно использовать в композиции с
filter(), чтобы убедиться, что предикату удовлетворяет ровно один элемент.
use IterTools\Stream;
$result = Stream::of([1, 2, 3, 4, 5])
->filter(fn (int $n) => $n === 3)
->toOnly();
// 3
To Percentile
Возвращает значение коллекции из потока для заданного процентиля.
$stream->toPercentile(float $percentile): int|float|null
- Используется метод R-7 / линейной интерполяции (по умолчанию в NumPy). Процентиль
0— это минимум,100— максимум. - Аргумент
$percentileдолжен находиться в диапазоне[0, 100]; иначе выбрасывается\InvalidArgumentException. - Интерполяция не переполняется, даже если расстояние между двумя соседними значениями превышает
PHP_FLOAT_MAX. - Процентиль
50для любого источника возвращает ровно то же, что иtoMedian. - Для пустой коллекции вернет
null.
use IterTools\Stream;
$scores = [10, 20, 30, 40, 50];
$p75 = Stream::of($scores)
->toPercentile(75);
// 40
To Product
Возвращает произведение элементов коллекции из потока.
$stream->toProduct(): mixed
Для пустой коллекции вернет null.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($iterable)
->toProduct();
// 120
To Quantile
Возвращает значение коллекции из потока для заданного квантиля.
$stream->toQuantile(float $quantile): int|float|null
- Принимает квантиль в диапазоне
[0, 1](например,0.25— первый квартиль / 25-й процентиль). - Аргумент
$quantileдолжен находиться в диапазоне[0, 1]; иначе выбрасывается\InvalidArgumentException. - Для пустой коллекции вернет
null.
use IterTools\Stream;
$scores = [10, 20, 30, 40, 50];
$q3 = Stream::of($scores)
->toQuantile(0.75);
// 40
To Random Value
Возвращает случайный элемент из коллекции потока.
$stream->toRandomValue(): mixed
use IterTools\Stream;
$rpsHands = ['rock', 'paper', 'scissors']
$range = Stream::of($numbers)
->map('strtoupper')
->toRandomValue();
// e.g., rock
To Range
Возвращает разницу между максимальным и минимальным элементами коллекции из потока.
$stream->toRange(): int|float
Для пустой коллекции вернет 0.
use IterTools\Stream;
$grades = [100, 90, 80, 85, 95];
$range = Stream::of($numbers)
->toRange();
// 20
To Standard Deviation
Возвращает стандартное отклонение значений коллекции из потока.
$stream->toStandardDeviation(bool $sample = false): float|null
- Квадратный корень из дисперсии. По умолчанию — стандартное отклонение генеральной совокупности; при
$sample = true— выборочное (поправка Бесселя). - Наследует от
toVarianceоднопроходность, памятьO(1)и поведение при переполнении. - Возвращает
nullдля пустой коллекции или для выборочного стандартного отклонения единственного значения. Случаи сnullимеют приоритет надNAN, как и вtoVariance.
use IterTools\Stream;
$numbers = [2, 4, 4, 4, 5, 5, 7, 9];
$stddev = Stream::of($numbers)
->toStandardDeviation();
// 2.0
To String
Преобразует коллекцию из потока в строку, "склеивая" ее элементы.
- Значение необязательного аргумента
$separatorвставляется в качестве разделителя между элементами в строке. - Значение необязательного аргумента
$prefixвставляется в начало строки. - Значение необязательного аргумента
$suffixвставляется в конец строки.
$stream->toString(string $separator = '', string $prefix = '', string $suffix = ''): string
use IterTools\Stream;
$words = ['IterTools', 'PHP', 'v1.0'];
$string = Stream::of($words)->toString($words);
// IterToolsPHPv1.0
$string = Stream::of($words)->toString($words, '-');
// IterTools-PHP-v1.0
$string = Stream::of($words)->toString($words, '-', 'Library: ');
// Library: IterTools-PHP-v1.0
$string = Stream::of($words)->toString($words, '-', 'Library: ', '!');
// Library: IterTools-PHP-v1.0!
To Sum
Возвращает сумму элементов коллекции из потока.
$stream->toSum(): mixed
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($iterable)
->toSum();
// 15
To Value
Редуцирует коллекцию из потока до значения, вычисляемого с использованием callback-функции.
В отличие от array_reduce(), работает с любыми iterable типами.
$stream->toValue(callable $reducer, mixed $initialValue): mixed
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($iterable)
->toValue(fn ($carry, $item) => $carry + $item);
// 15
To Variance
Возвращает дисперсию значений коллекции из потока.
$stream->toVariance(bool $sample = false): float|null
- По умолчанию — дисперсия генеральной совокупности; при
$sample = true— выборочная дисперсия (поправка Бесселя). - Используется масштабированный онлайн-алгоритм с компенсированным текущим средним: один проход с памятью
O(1), поэтому поток не материализуется. - Результат устойчив к порядку источника с точностью до ошибок округления, но не воспроизводится побитово: разные порядки могут отличаться на последний ulp.
- Остаётся конечным всегда, когда дисперсия представима, даже если промежуточные величины уже нет (дисперсия
[-1.4e154, 1.4e154, 0]равна~1.31e308, хотя дисперсия её первых двух значений уже превышаетPHP_FLOAT_MAX). - Любое неконечное значение в источнике даёт
NAN, так как отклонения от бесконечного среднего — этоINF - INF. Дисперсия, которую действительно невозможно представить, возвращается какINF, но никогда как отрицательное число. - Возвращает
nullдля пустой коллекции или для выборочной дисперсии единственного значения. Случаи сnullимеют приоритет надNAN:toVariance([INF], true)возвращаетnull, аtoVariance([INF])—NAN.
use IterTools\Stream;
$numbers = [1, 2, 3, 4, 5];
$variance = Stream::of($numbers)
->toVariance();
// 2.0
Операции конвертации
To Array
Возвращает массив всех элементов из потока.
$stream->toArray(): array
use IterTools\Stream;
$array = Stream::of([1, 1, 2, 2, 3, 4, 5])
->distinct()
->map(fn ($x) => $x**2)
->toArray();
// [1, 4, 9, 16, 25]
To Associative Array
Возвращает ассоциативный массив всех элементов из потока.
$stream->toAssociativeArray(callable $keyFunc, callable $valueFunc): array
use IterTools\Stream;
$keyFunc
$array = Stream::of(['message 1', 'message 2', 'message 3'])
->map('strtoupper')
->toAssociativeArray(
fn ($s) => \md5($s),
fn ($s) => $s
);
// [3b3f2272b3b904d342b2d0df2bf31ed4 => MESSAGE 1, 43638d919cfb8ea31979880f1a2bb146 => MESSAGE 2, ... ]
To Partition
Разделяет поток на два списка на основе предиката.
Возвращает массив из двух списков: [истинные значения, ложные значения]. Оба выходных массива — списки с переиндексацией (с нулевыми индексами); ключи исходной коллекции отбрасываются. Значение, возвращаемое предикатом, приводится к булевому типу через (bool).
$stream->toPartition(callable $predicate): array
use IterTools\Stream;
[$evens, $odds] = Stream::of([1, 2, 3, 4, 5, 6])
->toPartition(fn (int $n): bool => $n % 2 === 0);
// $evens: [2, 4, 6]
// $odds: [1, 3, 5]
Так как обе части возвращаются вместе, toPartition естественно сочетается с операциями, потребляющими два списка. Например, при составлении турнирной сетки — разделяем номера посева на верхнюю и нижнюю половины, затем образуем пары верх vs перевёрнутая нижняя половина:
use IterTools\Stream;
[$topHalf, $bottomHalf] = Stream::of([1, 2, 3, 4, 5, 6, 7, 8])
->toPartition(fn (int $seed): bool => $seed <= 4);
$matchups = Stream::of($topHalf)
->zipWith(array_reverse($bottomHalf))
->toArray();
// [[1, 8], [2, 7], [3, 6], [4, 5]]
Tee
Создает несколько одинаковых независимых потоков из данной коллекции.
$stream->tee(int $count): array
use IterTools\Transform;
$daysOfWeek = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'];
$count = 3;
[$week1Stream, $week2Stream, $week3Stream] = Stream::of($daysOfWeek)
->tee($count);
// Каждый $weekStream содержит ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
Операции с побочными эффектами
Call For Each
Вызывает callback-функцию для каждого элемента из потока.
$stream->callForEach(callable $function): void
use IterTools\Stream;
$languages = ['PHP', 'Python', 'Java', 'Go'];
$mascots = ['elephant', 'snake', 'bean', 'gopher'];
$zipPrinter = fn ($zipped) => print("{$zipped[0]}'s mascot: {$zipped[1]}");
Stream::of($languages)
->zipWith($mascots)
->callForEach($zipPrinter);
// PHP's mascot: elephant
// Python's mascot: snake
// ...
Consume
Полностью обходит поток, отбрасывая значения.
Полезно для принудительного выполнения «ленивого» конвейера, нужного только ради побочных эффектов (например, map() с побочным эффектом).
$stream->consume(): void
use IterTools\Stream;
$log = [];
$pipeline = Stream::of([1, 2, 3])
->map(function (int $n) use (&$log): int {
$log[] = $n;
return $n * 2;
});
// $log === [] (map ленивая — пока ничего не выполнилось)
$pipeline->consume();
// $log === [1, 2, 3]
Вызывает print() для каждого элемента из потока.
- Элементы в потоке должны иметь строковое представление.
$stream->print(string $separator = '', string $prefix = '', string $suffix = ''): void
use IterTools\Stream;
$words = ['IterTools', 'PHP', 'v1.0'];
Stream::of($words)->print(); // IterToolsPHPv1.0
Stream::of($words)->print('-'); // IterTools-PHP-v1.0
Stream::of($words)->print('-', 'Library: '); // Library: IterTools-PHP-v1.0
Stream::of($words)->print('-', 'Library: ', '!'); // Library: IterTools-PHP-v1.0!
Print Line
Печатает элементы из потока каждый с новой строки.
- Элементы в потоке должны иметь строковое представление.
$stream->println(): void
use IterTools\Stream;
$words = ['IterTools', 'PHP', 'v1.0'];
Stream::of($words)->printLn();
// IterTools
// PHP
// v1.0
To CSV File
Записывает содержимое потока в CSV файл.
$stream->toCsvFile(resource $fileHandle, array $header = null, string 'separator = ',', string $enclosure = '"', string $escape = '\\'): void
use IterTools\Stream;
$starWarsMovies = [
['Star Wars: Episode IV – A New Hope', 'IV', 1977],
['Star Wars: Episode V – The Empire Strikes Back', 'V', 1980],
['Star Wars: Episode VI – Return of the Jedi', 'VI', 1983],
];
$header = ['title', 'episode', 'year'];
Stream::of($data)
->toCsvFile($fh, $header);
// title,episode,year
// "Star Wars: Episode IV – A New Hope",IV,1977
// "Star Wars: Episode V – The Empire Strikes Back",V,1980
// "Star Wars: Episode VI – Return of the Jedi",VI,1983
To File
Записывает содержимое потока в файл.
$stream->toFile(resource $fileHandle, string $newLineSeparator = \PHP_EOL, string $header = null, string $footer = null): void
use IterTools\Stream;
$data = ['item1', 'item2', 'item3'];
$header = '<ul>';
$footer = '</ul>';
Stream::of($data)
->map(fn ($item) => " <li>$item</li>")
->toFile($fh, \PHP_EOL, $header, $footer);
// <ul>
// <li>item1</li>
// <li>item2</li>
// <li>item3</li>
// </ul>
Операции для дебаггинга
Peek
Позволяет просмотреть каждый элемент между другими потоковыми операциями, чтобы выполнить какое-либо действие без влияния на поток.
Ленивая операция: колбэк вызывается один раз для каждого элемента в тот момент, когда нижестоящая операция вытягивает этот элемент из потока. Элементы, которые ниже по потоку не потребляются, не просматриваются.
$stream->peek(callable $callback): Stream
use IterTools\Stream;
$logger = new SimpleLog\Logger('/tmp/log.txt', 'iterTools');
Stream::of(['some', 'items'])
->map('strtoupper')
->peek(fn ($x) => $logger->info($x))
->foreach($someComplexCallable);
Peek Stream
Позволяет просмотреть коллекцию потока между другими потоковыми операциями, чтобы выполнить какое-либо действие без влияния на поток.
Работает с потоком целиком и является нетерпеливой (eager) операцией: в отличие от поэлементного peek, колбэк вызывается один раз в момент вызова peekStream(), до выполнения каких-либо нижестоящих операций. Колбэк получает собственный поток над копией источника; потребление этого потока внутри колбэка буферизует источник, чтобы основной поток мог затем воспроизвести его.
$stream->peekStream(callable $callback): Stream
use IterTools\Stream;
$logger = new SimpleLog\Logger('/tmp/log.txt', 'iterTools');
Stream::of(['some', 'items'])
->map('strtoupper')
->peekStream(fn ($stream) => $logger->info($stream))
->foreach($someComplexCallable);
Peek Print
Распечатывает каждый элемент хранимой коллекции в поток вывода между другими потоковыми операциями.
Нетерпеливая (eager) операция: делегирует в peekStream, поэтому весь источник печатается и буферизуется в момент вызова peekPrint(), до выполнения каких-либо нижестоящих операций. Поэлементная ленивость peek здесь не действует.
$stream->peekPrint(string $separator = '', string $prefix = '', string $suffix = ''): Stream
use IterTools\Stream;
Stream::of(['some', 'items'])
->map('strtoupper')
->peekPrint()
->foreach($someComplexCallable);
Peek PrintR
Вызывает print_r() для каждого элемента хранимой коллекции между другими потоковыми операциями.
Нетерпеливая (eager) операция: делегирует в peekStream, поэтому весь источник печатается и буферизуется в момент вызова peekPrintR(), до выполнения каких-либо нижестоящих операций. Поэлементная ленивость peek здесь не действует.
$stream->peekPrintR(): Stream
use IterTools\Stream;
Stream::of(['some', 'items'])
->map('strtoupper')
->peekPrintR()
->foreach($someComplexCallable);
Print R
Вызывает print_r() для каждого элемента из потока.
$stream->printR(): void
use IterTools\Stream;
$items = [$string, $array, $object];
Stream::of($words)->printR();
// print_r output
Var Dump
Вызывает var_dump() для каждого элемента из потока.
$stream->varDump(): void
use IterTools\Stream;
$items = [$string, $array, $object];
Stream::of($words)->varDump();
// var_dump output