Stars: 134
Forks: 10
Pull Requests: 49
Issues: 6
Watchers: 5
Last Updated: 2023-09-09 23:04:35
PHP Iteration Tools Library
License: MIT License
Languages: Makefile, PHP
Inspired by Python—designed for PHP.
IterTools makes you an iteration superstar by providing two types of tools:
Loop Iteration Tools Example
foreach (Multi::zip(['a', 'b'], [1, 2]) as [$letter, $number]) {
print($letter . $number); // a1, b2
}
Stream Iteration Tools Example
$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]
->filter(fn ($x) => $x < 10) // [1, 4, 9]
->toSum(); // 14
All functions work on iterable
collections:
array
(type)Generator
(type)Iterator
(interface)Traversable
(interface)Iterator | Description | Code Snippet |
---|---|---|
chain |
Chain multiple iterables together | Multi::chain($list1, $list2) |
zip |
Iterate multiple collections simultaneously until the shortest iterator completes | Multi::zip($list1, $list2) |
zipEqual |
Iterate multiple collections of equal length simultaneously, error if lengths not equal | Multi::zipEqual($list1, $list2) |
zipFilled |
Iterate multiple collections, using a filler value if lengths not equal | Multi::zipFilled($default, $list1, $list2) |
zipLongest |
Iterate multiple collections simultaneously until the longest iterator completes | Multi::zipLongest($list1, $list2) |
Iterator | Description | Code Snippet |
---|---|---|
chunkwise |
Iterate by chunks | Single::chunkwise($data, $chunkSize) |
chunkwiseOverlap |
Iterate by overlapped chunks | Single::chunkwiseOverlap($data, $chunkSize, $overlapSize) |
compress |
Filter out elements not selected | Single::compress($data, $selectors) |
compressAssociative |
Filter out elements by keys not selected | Single::compressAssociative($data, $selectorKeys) |
dropWhile |
Drop elements while predicate is true | Single::dropWhile($data, $predicate) |
filter |
Filter for elements where predicate is true | Single::filterTrue($data, $predicate) |
filterTrue |
Filter for truthy elements | Single::filterTrue($data) |
filterFalse |
Filter for falsy elements | Single::filterFalse($data) |
filterKeys |
Filter for keys where predicate is true | Single::filterKeys($data, $predicate) |
flatMap |
Map function onto items and flatten result | Single::flaMap($data, $mapper) |
flatten |
Flatten multidimensional iterable | Single::flatten($data, [$dimensions]) |
groupBy |
Group data by a common element | Single::groupBy($data, $groupKeyFunction, [$itemKeyFunc]) |
limit |
Iterate up to a limit | Single::limit($data, $limit) |
map |
Map function onto each item | Single::map($data, $function) |
pairwise |
Iterate successive overlapping pairs | Single::pairwise($data) |
reindex |
Reindex keys of key-value iterable | Single::reindex($data, $reindexer) |
repeat |
Repeat an item a number of times | Single::repeat($item, $repetitions) |
reverse |
Iterate elements in reverse order | Single::reverse($data) |
skip |
Iterate after skipping elements | Single::skip($data, $count, [$offset]) |
slice |
Extract a slice of the iterable | Single::slice($data, [$start], [$count], [$step]) |
string |
Iterate the characters of a string | Single::string($string) |
takeWhile |
Iterate elements while predicate is true | Single::takeWhile($data, $predicate) |
Iterator | Description | Code Snippet |
---|---|---|
count |
Count sequentially forever | Infinite::count($start, $step) |
cycle |
Cycle through a collection | Infinite::cycle($collection) |
repeat |
Repeat an item forever | Infinite::repeat($item) |
Iterator | Description | Code Snippet |
---|---|---|
choice |
Random selections from list | Random::choice($list, $repetitions) |
coinFlip |
Random coin flips (0 or 1) | Random::coinFlip($repetitions) |
number |
Random numbers | Random::number($min, $max, $repetitions) |
percentage |
Random percentage between 0 and 1 | Random::percentage($repetitions) |
rockPaperScissors |
Random rock-paper-scissors hands | Random::rockPaperScissors($repetitions) |
Iterator | Description | Code Snippet |
---|---|---|
frequencies |
Frequency distribution of data | Math::frequencies($data, [$strict]) |
relativeFrequencies |
Relative frequency distribution of data | Math::relativeFrequencies($data, [$strict]) |
runningAverage |
Running average accumulation | Math::runningAverage($numbers, $initialValue) |
runningDifference |
Running difference accumulation | Math::runningDifference($numbers, $initialValue) |
runningMax |
Running maximum accumulation | Math::runningMax($numbers, $initialValue) |
runningMin |
Running minimum accumulation | Math::runningMin($numbers, $initialValue) |
runningProduct |
Running product accumulation | Math::runningProduct($numbers, $initialValue) |
runningTotal |
Running total accumulation | Math::runningTotal($numbers, $initialValue) |
Iterator | Description | Code Snippet |
---|---|---|
distinct |
Iterate only distinct items | Set::distinct($data) |
distinctBy |
Iterate only distinct items using custom comparator | Set::distinct($data, $compareBy) |
intersection |
Intersection of iterables | Set::intersection(...$iterables) |
intersectionCoercive |
Intersection with type coercion | Set::intersectionCoercive(...$iterables) |
partialIntersection |
Partial intersection of iterables | Set::partialIntersection($minCount, ...$iterables) |
partialIntersectionCoercive |
Partial intersection with type coercion | Set::partialIntersectionCoercive($minCount, ...$iterables) |
symmetricDifference |
Symmetric difference of iterables | Set::symmetricDifference(...$iterables) |
symmetricDifferenceCoercive |
Symmetric difference with type coercion | Set::symmetricDifferenceCoercive(...$iterables) |
union |
Union of iterables | Set::union(...$iterables) |
unionCoercive |
Union with type coercion | Set::unionCoercive(...$iterables) |
Iterator | Description | Code Snippet |
---|---|---|
asort |
Iterate a sorted collection maintaining keys | Sort::asort($data, [$comparator]) |
sort |
Iterate a sorted collection | Sort::sort($data, [$comparator]) |
Iterator | Description | Code Snippet |
---|---|---|
readCsv |
Intersection a CSV file line by line | File::readCsv($fileHandle) |
readLines |
Iterate a file line by line | File::readLines($fileHandle) |
Iterator | Description | Code Snippet |
---|---|---|
tee |
Iterate duplicate iterators | Transform::tee($data, $count) |
toArray |
Transform iterable to an array | Transform::toArray($data) |
toAssociativeArray |
Transform iterable to an associative array | Transform::toAssociativeArray($data, [$keyFunc], [$valueFunc]) |
toIterator |
Transform iterable to an iterator | Transform::toIterator($data) |
Summary | Description | Code Snippet |
---|---|---|
allMatch |
True if all items are true according to predicate | Summary::allMatch($data, $predicate) |
allUnique |
True if all items are unique | Summary::allUnique($data, [$strict]) |
anyMatch |
True if any item is true according to predicate | Summary::anyMatch($data, $predicate) |
arePermutations |
True if iterables are permutations of each other | Summary::arePermutations(...$iterables) |
arePermutationsCoercive |
True if iterables are permutations of each other with type coercion | Summary::arePermutationsCoercive(...$iterables) |
exactlyN |
True if exactly n items are true according to predicate | Summary::exactlyN($data, $n, $predicate) |
isEmpty |
True if iterable has no items | Summary::isEmpty($data) |
isPartitioned |
True if partitioned with items true according to predicate before others | Summary::isPartitioned($data, $predicate) |
isSorted |
True if iterable sorted | Summary::isSorted($data) |
isReversed |
True if iterable reverse sorted | Summary::isReversed($data) |
noneMatch |
True if none of items true according to predicate | Summary::noneMatch($data, $predicate) |
same |
True if iterables are the same | Summary::same(...$iterables) |
sameCount |
True if iterables have the same lengths | Summary::sameCount(...$iterables) |
Reducer | Description | Code Snippet |
---|---|---|
toAverage |
Mean average of elements | Reduce::toAverage($numbers) |
toCount |
Reduce to length of iterable | Reduce::toCount($data) |
toFirst |
Reduce to its first value | Reduce::toFirst($data) |
toFirstAndLast |
Reduce to its first and last values | Reduce::toFirstAndLast($data) |
toLast |
Reduce to its last value | Reduce::toLast() |
toMax |
Reduce to its largest element | Reduce::toMax($numbers, [$compareBy]) |
toMin |
Reduce to its smallest element | Reduce::toMin($numbers, [$compareBy]) |
toMinMax |
Reduce to array of upper and lower bounds | Reduce::toMinMax($numbers, [$compareBy]) |
toNth |
Reduce to value at nth position | Reduce::toNth($data, $position) |
toProduct |
Reduce to the product of its elements | Reduce::toProduct($numbers) |
toRandomValue |
Reduce to random value from iterable | Reduce::toRandomValue($data) |
toRange |
Reduce to difference of max and min values | Reduce::toRange($numbers) |
toString |
Reduce to joined string | Reduce::toString($data, [$separator], [$prefix], [$suffix]) |
toSum |
Reduce to the sum of its elements | Reduce::toSum($numbers) |
toValue |
Reduce to value using callable reducer | Reduce::toValue($data, $reducer, $initialValue) |
Source | Description | Code Snippet |
---|---|---|
of |
Create a stream from an iterable | Stream::of($iterable) |
ofCoinFlips |
Create a stream of random coin flips | Stream::ofCoinFlips($repetitions) |
ofCsvFile |
Create a stream from a CSV file | Stream::ofCsvFile($fileHandle) |
ofEmpty |
Create an empty stream | Stream::ofEmpty() |
ofFileLines |
Create a stream from lines of a file | Stream::ofFileLines($fileHandle) |
ofRandomChoice |
Create a stream of random selections | Stream::ofRandomChoice($items, $repetitions) |
ofRandomNumbers |
Create a stream of random numbers (integers) | Stream::ofRandomNumbers($min, $max, $repetitions) |
ofRandomPercentage |
Create a stream of random percentages between 0 and 1 | Stream::ofRandomPercentage($repetitions) |
ofRange |
Create a stream of a range of numbers | Stream::ofRange($start, $end, $step) |
ofRockPaperScissors |
Create a stream of rock-paper-scissors hands | Stream::ofRockPaperScissors($repetitions) |
Operation | Description | Code Snippet |
---|---|---|
asort |
Sorts the iterable source maintaining keys | $stream->asort([$comparator]) |
chainWith |
Chain iterable source withs given iterables together into a single iteration | $stream->chainWith(...$iterables) |
compress |
Compress source by filtering out data not selected | $stream->compress($selectors) |
compressAssociative |
Compress source by filtering out keys not selected | $stream->compressAssociative($selectorKeys) |
chunkwise |
Iterate by chunks | $stream->chunkwise($chunkSize) |
chunkwiseOverlap |
Iterate by overlapped chunks | $stream->chunkwiseOverlap($chunkSize, $overlap) |
distinct |
Filter out elements: iterate only unique items | $stream->distinct([$strict]) |
distinctBy |
Filter out elements: iterate only unique items using custom comparator | $stream->distinct($compareBy) |
dropWhile |
Drop elements from the iterable source while the predicate function is true | $stream->dropWhile($predicate) |
filter |
Filter for only elements where the predicate function is true | $stream->filterTrue($predicate) |
filterTrue |
Filter for only truthy elements | $stream->filterTrue() |
filterFalse |
Filter for only falsy elements | $stream->filterFalse() |
filterKeys |
Filter for keys where predicate function is true | $stream->filterKeys($predicate) |
flatMap |
Map function onto elements and flatten result | $stream->flatMap($function) |
flatten |
Flatten multidimensional stream | $stream->flatten($dimensions) |
frequencies |
Frequency distribution | $stream->frequencies([$strict]) |
groupBy |
Group iterable source by a common data element | $stream->groupBy($groupKeyFunction, [$itemKeyFunc]) |
infiniteCycle |
Cycle through the elements of iterable source sequentially forever | $stream->infiniteCycle() |
intersectionWith |
Intersect iterable source and given iterables | $stream->intersectionWith(...$iterables) |
intersection CoerciveWith |
Intersect iterable source and given iterables with type coercion | $stream->intersectionCoerciveWith(...$iterables) |
limit |
Limit the stream's iteration | $stream->limit($limit) |
map |
Map function onto elements | $stream->map($function) |
pairwise |
Return pairs of elements from iterable source | $stream->pairwise() |
partialIntersectionWith |
Partially intersect iterable source and given iterables | $stream->partialIntersectionWith( $minIntersectionCount, ...$iterables) |
partialIntersection CoerciveWith |
Partially intersect iterable source and given iterables with type coercion | $stream->partialIntersectionCoerciveWith( $minIntersectionCount, ...$iterables) |
reindex |
Reindex keys of key-value stream | $stream->reindex($reindexer) |
relativeFrequencies |
Relative frequency distribution | $stream->relativeFrequencies([$strict]) |
reverse |
Reverse elements of the stream | $stream->reverse() |
runningAverage |
Accumulate the running average (mean) over iterable source | $stream->runningAverage($initialValue) |
runningDifference |
Accumulate the running difference over iterable source | $stream->runningDifference($initialValue) |
runningMax |
Accumulate the running max over iterable source | $stream->runningMax($initialValue) |
runningMin |
Accumulate the running min over iterable source | $stream->runningMin($initialValue) |
runningProduct |
Accumulate the running product over iterable source | $stream->runningProduct($initialValue) |
runningTotal |
Accumulate the running total over iterable source | $stream->runningTotal($initialValue) |
skip |
Skip some elements of the stream | $stream->skip($count, [$offset]) |
slice |
Extract a slice of the stream | $stream->slice([$start], [$count], [$step]) |
sort |
Sorts the stream | $stream->sort([$comparator]) |
symmetricDifferenceWith |
Symmetric difference of iterable source and given iterables | $this->symmetricDifferenceWith(...$iterables) |
symmetricDifference CoerciveWith |
Symmetric difference of iterable source and given iterables with type coercion | $this->symmetricDifferenceCoerciveWith( ...$iterables) |
takeWhile |
Return elements from the iterable source as long as the predicate is true | $stream->takeWhile($predicate) |
unionWith |
Union of stream with iterables | $stream->unionWith(...$iterables) |
unionCoerciveWith |
Union of stream with iterables with type coercion | $stream->unionCoerciveWith(...$iterables) |
zipWith |
Iterate iterable source with another iterable collection simultaneously | $stream->zipWith(...$iterables) |
zipEqualWith |
Iterate iterable source with another iterable collection of equal lengths simultaneously | $stream->zipEqualWith(...$iterables) |
zipFilledWith |
Iterate iterable source with another iterable collection using default filler | $stream->zipFilledWith($default, ...$iterables) |
zipLongestWith |
Iterate iterable source with another iterable collection simultaneously | $stream->zipLongestWith(...$iterables) |
Terminal Operation | Description | Code Snippet |
---|---|---|
allMatch |
Returns true if all items in stream match predicate | $stream->allMatch($predicate) |
allUnique |
Returns true if all items in stream are unique | $stream->allUnique([$strict]]) |
anyMatch |
Returns true if any item in stream matches predicate | $stream->anyMatch($predicate) |
arePermutationsWith |
Returns true if all iterables permutations of stream | $stream->arePermutationsWith(...$iterables) |
arePermutationsCoerciveWith |
Returns true if all iterables permutations of stream with type coercion | $stream->arePermutationsCoerciveWith(...$iterables) |
exactlyN |
Returns true if exactly n items are true according to predicate | $stream->exactlyN($n, $predicate) |
isEmpty |
Returns true if stream has no items | $stream::isEmpty() |
isPartitioned |
Returns true if partitioned with items true according to predicate before others | $stream::isPartitioned($predicate) |
isSorted |
Returns true if stream is sorted in ascending order | $stream->isSorted() |
isReversed |
Returns true if stream is sorted in reverse descending order | $stream->isReversed() |
noneMatch |
Returns true if none of the items in stream match predicate | $stream->noneMatch($predicate) |
sameWith |
Returns true if stream and all given collections are the same | $stream->sameWith(...$iterables) |
sameCountWith |
Returns true if stream and all given collections have the same lengths | $stream->sameCountWith(...$iterables) |
Terminal Operation | Description | Code Snippet |
---|---|---|
toAverage |
Reduces stream to the mean average of its items | $stream->toAverage() |
toCount |
Reduces stream to its length | $stream->toCount() |
toFirst |
Reduces stream to its first value | $stream->toFirst() |
toFirstAndLast |
Reduces stream to its first and last values | $stream->toFirstAndLast() |
toLast |
Reduces stream to its last value | $stream->toLast() |
toMax |
Reduces stream to its max value | $stream->toMax([$compareBy]) |
toMin |
Reduces stream to its min value | $stream->toMin([$compareBy]) |
toMinMax |
Reduces stream to array of upper and lower bounds | $stream->toMinMax([$compareBy]) |
toNth |
Reduces stream to value at nth position | $stream->toNth($position) |
toProduct |
Reduces stream to the product of its items | $stream->toProduct() |
toString |
Reduces stream to joined string | $stream->toString([$separator], [$prefix], [$suffix]) |
toSum |
Reduces stream to the sum of its items | $stream->toSum() |
toRandomValue |
Reduces stream to random value within it | $stream->toRandomValue() |
toRange |
Reduces stream to difference of max and min values | $stream->toRange() |
toValue |
Reduces stream like array_reduce() function | $stream->toValue($reducer, $initialValue) |
Terminal Operation | Description | Code Snippet |
---|---|---|
toArray |
Returns array of stream elements | $stream->toArray() |
toAssociativeArray |
Returns key-value map of stream elements | $stream->toAssociativeArray($keyFunc, $valueFunc) |
tee |
Returns array of multiple identical Streams | $stream->tee($count) |
Terminal Operation | Description | Code Snippet |
---|---|---|
callForEach |
Perform action via function on each item | $stream->callForEach($function) |
print |
print each item in the stream |
$stream->print([$separator], [$prefix], [$suffix]) |
printLn |
print each item on a new line |
$stream->printLn() |
toCsvFile |
Write the contents of the stream to a CSV file | $stream->toCsvFile($fileHandle, [$headers]) |
toFile |
Write the contents of the stream to a file | $stream->toFile($fileHandle) |
Debug Operation | Description | Code Snippet |
---|---|---|
peek |
Peek at each element between stream operations | $stream->peek($peekFunc) |
peekStream |
Peek at the entire stream between operations | $stream->peekStream($peekFunc) |
peekPrint |
Peek at each element by printing between operations | $stream->peekPrint() |
peekPrintR |
Peek at each element by doing print-r between operations | $stream->peekPrintR() |
printR |
print_r each item |
$stream->printR() |
varDump |
var_dump each item |
$stream->varDump() |
Add the library to your composer.json
file in your project:
{
"require": {
"markrogoyski/itertools-php": "1.*"
}
}
Use composer to install the library:
$ php composer.phar install
Composer will install IterTools inside your vendor folder. Then you can add the following to your .php files to use the library with Autoloading.
require_once __DIR__ . '/vendor/autoload.php';
Alternatively, use composer on the command line to require and install IterTools:
$ php composer.phar require markrogoyski/itertools-php:1.*
All functions work on iterable
collections:
array
(type)Generator
(type)Iterator
(interface)Traversable
(interface)Chain multiple iterables together into a single continuous sequence.
Multi::chain(iterable ...$iterables)
use IterTools\Multi;
$prequels = ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith'];
$originals = ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi'];
foreach (Multi::chain($prequels, $originals) as $movie) {
print($movie);
}
// 'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith', 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi'
Iterate multiple iterable collections simultaneously.
Multi::zip(iterable ...$iterables)
use IterTools\Multi;
$languages = ['PHP', 'Python', 'Java', 'Go'];
$mascots = ['elephant', 'snake', 'bean', 'gopher'];
foreach (Multi::zip($languages, $mascots) as [$language, $mascot]) {
print("The {$language} language mascot is an {$mascot}.");
}
// The PHP language mascot is an elephant.
// ...
Zip works with multiple iterable inputs--not limited to just two.
$names = ['Ryu', 'Ken', 'Chun Li', 'Guile'];
$countries = ['Japan', 'USA', 'China', 'USA'];
$signatureMoves = ['hadouken', 'shoryuken', 'spinning bird kick', 'sonic boom'];
foreach (Multi::zip($names, $countries, $signatureMoves) as [$name, $country, $signatureMove]) {
$streetFighter = new StreetFighter($name, $country, $signatureMove);
}
Note: For uneven lengths, iteration stops when the shortest iterable is exhausted.
Iterate multiple iterable collections with equal lengths simultaneously.
Throws \LengthException
if lengths are not equal, meaning that at least one iterator ends before the others.
Multi::zipEqual(iterable ...$iterables)
use IterTools\Multi;
$letters = ['A', 'B', 'C'];
$numbers = [1, 2, 3];
foreach (Multi::zipEqual($letters, $numbers) as [$letter, $number]) {
// ['A', 1], ['B', 2], ['C', 3]
}
Iterate multiple iterable collections simultaneously, using a default filler value if lengths are not equal.
Multi::zipFilled(mixed $filler, iterable ...$iterables)
use IterTools\Multi;
$default = '?';
$letters = ['A', 'B'];
$numbers = [1, 2, 3];
foreach (Multi::zipFilled($default, $letters, $numbers) as [$letter, $number]) {
// ['A', 1], ['B', 2], ['?', 3]
}
Iterate multiple iterable collections simultaneously.
Multi::zipLongest(iterable ...$iterables)
For uneven lengths, the exhausted iterables will produce null
for the remaining iterations.
use IterTools\Multi;
$letters = ['A', 'B', 'C'];
$numbers = [1, 2];
foreach (Multi::zipLongest($letters, $numbers) as [$letter, $number]) {
// ['A', 1], ['B', 2], ['C', null]
}
Return elements in chunks of a certain size.
Single::chunkwise(iterable $data, int $chunkSize)
Chunk size must be at least 1.
use IterTools\Single;
$movies = [
'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith',
'A New Hope', 'Empire Strikes Back', 'Return of the Jedi',
'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'
];
foreach (Single::chunkwise($movies, 3) as $trilogy) {
$trilogies[] = $trilogy;
}
// [
// ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith'],
// ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi'],
// ['The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker]'
// ]
Return overlapped chunks of elements.
Single::chunkwiseOverlap(iterable $data, int $chunkSize, int $overlapSize, bool $includeIncompleteTail = true)
use IterTools\Single;
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
foreach (Single::chunkwiseOverlap($numbers, 3, 1) as $chunk) {
// [1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]
}
Compress an iterable by filtering out data that is not selected.
Single::compress(string $data, $selectors)
use IterTools\Single;
$movies = [
'Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith',
'A New Hope', 'Empire Strikes Back', 'Return of the Jedi',
'The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'
];
$goodMovies = [0, 0, 0, 1, 1, 1, 1, 0, 0];
foreach (Single::compress($movies, $goodMovies) as $goodMovie) {
print($goodMovie);
}
// 'A New Hope', 'Empire Strikes Back', 'Return of the Jedi', 'The Force Awakens'
Compress an iterable by filtering out keys that are not selected.
Single::compressAssociative(string $data, array $selectorKeys)
use IterTools\Single;
$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',
];
$originalTrilogyNumbers = ['IV', 'V', 'VI'];
foreach (Single::compressAssociative($starWarsEpisodes, $originalTrilogyNumbers) as $episode => $title) {
print("$episode: $title" . \PHP_EOL);
}
// IV: A New Hope
// V: The Empire Strikes Back
// VI: Return of the Jedi
Drop elements from the iterable while the predicate function is true.
Once the predicate function returns false once, all remaining elements are returned.
Single::dropWhile(iterable $data, callable $predicate)
use IterTools\Single;
$scores = [50, 60, 70, 85, 65, 90];
$predicate = fn ($x) => $x < 70;
foreach (Single::dropWhile($scores, $predicate) as $score) {
print($score);
}
// 70, 85, 65, 90
Filter out elements from the iterable only returning elements where the predicate function is true.
Single::filter(iterable $data, callable $predicate)
use IterTools\Single;
$starWarsEpisodes = [1, 2, 3, 4, 5, 6, 7, 8, 9];
$goodMoviePredicate = fn ($episode) => $episode > 3 && $episode < 8;
foreach (Single::filter($starWarsEpisodes, $goodMoviePredicate) as $goodMovie) {
print($goodMovie);
}
// 4, 5, 6, 7
Filter out elements from the iterable only returning elements that are truthy.
Single::filterTrue(iterable $data)
use IterTools\Single;
$reportCardGrades = [100, 0, 95, 85, 0, 94, 0];
foreach (Single::filterTrue($reportCardGrades) as $goodGrade) {
print($goodGrade);
}
// 100, 95, 85, 94
Filter out elements from the iterable only returning elements where the predicate function is false.
If no predicate is provided, the boolean value of the data is used.
Single::filterFalse(iterable $data, callable $predicate)
use IterTools\Single;
$alerts = [0, 1, 1, 0, 1, 0, 0, 1, 1];
foreach (Single::filterFalse($alerts) as $noAlert) {
print($noAlert);
}
// 0, 0, 0, 0
Filter out elements from the iterable only returning elements for which keys the predicate function is true.
Single::filterKeys(iterable $data, callable $predicate)
use IterTools\Single;
$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',
];
$summerFilter = fn ($year) => $year % 4 === 0;
foreach (Single::filterKeys($olympics, $summerFilter) as $year => $hostCity) {
print("$year: $hostCity" . \PHP_EOL);
}
// 2000: Sydney
// 2004: Athens
// 2008: Beijing
// 2012: London
// 2016: Rio de Janeiro
// 2020: Tokyo
Map a function only the elements of the iterable and then flatten the results.
Single::flatMap(iterable $data, callable $mapper)
use IterTools\Single;
$data = [1, 2, 3, 4, 5];
$mapper = fn ($item) => [$item, -$item];
foreach (Single::flatMap($data, $mapper) as $number) {
print($number . ' ');
}
// 1 -1 2 -2 3 -3 4 -4 5 -5
Flatten a multidimensional iterable.
Single::flatten(iterable $data, int $dimensions = 1)
use IterTools\Single;
$multidimensional = [1, [2, 3], [4, 5]];
$flattened = [];
foreach (Single::flatten($multidimensional) as $number) {
$flattened[] = $number;
}
// [1, 2, 3, 4, 5]
Group data by a common data element.
Single::groupBy(iterable $data, callable $groupKeyFunction, callable $itemKeyFunction = null)
$groupKeyFunction
determines the key to group elements by.$itemKeyFunction
allows custom indexes within each group member.use IterTools\Single;
$cartoonCharacters = [
['Garfield', 'cat'],
['Tom', 'cat'],
['Felix', 'cat'],
['Heathcliff', 'cat'],
['Snoopy', 'dog'],
['Scooby-Doo', 'dog'],
['Odie', 'dog'],
['Donald', 'duck'],
['Daffy', 'duck'],
];
$charactersGroupedByAnimal = [];
foreach (Single::groupBy($cartoonCharacters, fn ($x) => $x[1]) as $animal => $characters) {
$charactersGroupedByAnimal[$animal] = $characters;
}
/*
'cat' => [
['Garfield', 'cat'],
['Tom', 'cat'],
['Felix', 'cat'],
['Heathcliff', 'cat'],
],
'dog' => [
['Snoopy', 'dog'],
['Scooby-Doo', 'dog'],
['Odie', 'dog'],
],
'duck' => [
['Donald', 'duck'],
['Daffy', 'duck'],
*/
Iterate up to a limit.
Stops even if more data available if limit reached.
Single::limit(iterable $data, int $limit)
use IterTools\Single;
$matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections'];
$limit = 1;
foreach (Single::limit($matrixMovies, $limit) as $goodMovie) {
print($goodMovie);
}
// 'The Matrix' (and nothing else)
Map a function onto each element.
Single::map(iterable $data, callable $function)
use IterTools\Single;
$grades = [100, 99, 95, 98, 100];
$strictParentsOpinion = fn ($g) => $g === 100 ? 'A' : 'F';
foreach (Single::map($grades, $strictParentsOpinion) as $actualGrade) {
print($actualGrade);
}
// A, F, F, F, A
Returns successive overlapping pairs.
Returns empty generator if given collection contains fewer than 2 elements.
Single::pairwise(iterable $data)
use IterTools\Single;
$friends = ['Ross', 'Rachel', 'Chandler', 'Monica', 'Joey', 'Phoebe'];
foreach (Single::pairwise($friends) as [$leftFriend, $rightFriend]) {
print("{$leftFriend} and {$rightFriend}");
}
// Ross and Rachel, Rachel and Chandler, Chandler and Monica, ...
Repeat an item.
Single::repeat(mixed $item, int $repetitions)
use IterTools\Single;
$data = 'Beetlejuice';
$repetitions = 3;
foreach (Single::repeat($data, $repetitions) as $repeated) {
print($repeated);
}
// 'Beetlejuice', 'Beetlejuice', 'Beetlejuice'
Reindex keys of key-value iterable using indexer function.
Single::reindex(string $data, callable $indexer)
use IterTools\Single;
$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'];
$reindexedData = [];
foreach (Single::reindex($data, $reindexFunc) as $key => $filmData) {
$reindexedData[$key] = $filmData;
}
// [
// '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,
// ],
// ]
Reverse the elements of an iterable.
Single::reverse(iterable $data)
use IterTools\Single;
$words = ['Alice', 'answers', 'your', 'questions', 'Bob'];
foreach (Single::reverse($words) as $word) {
print($word . ' ');
}
// Bob questions your answers Alice
Skip n elements in the iterable after optional offset offset.
Single::skip(iterable $data, int $count, int $offset = 0)
use IterTools\Single;
$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'
];
$prequelsRemoved = [];
foreach (Single::skip($movies, 3) as $nonPrequel) {
$prequelsRemoved[] = $nonPrequel;
} // Episodes IV - IX
$onlyTheBest = [];
foreach (Single::skip($prequelsRemoved, 3, 3) as $nonSequel) {
$onlyTheBest[] = $nonSequel;
}
// 'A New Hope', 'The Empire Strikes Back', 'Return of the Jedi'
Extract a slice of the iterable.
Single::slice(iterable $data, int $start = 0, int $count = null, int $step = 1)
use IterTools\Single;
$olympics = [1992, 1994, 1996, 1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016, 2018, 2020, 2022];
$winterOlympics = [];
foreach (Single::slice($olympics, 1, 8, 2) as $winterYear) {
$winterOlympics[] = $winterYear;
}
// [1994, 1998, 2002, 2006, 2010, 2014, 2018, 2022]
Iterate the individual characters of a string.
Single::string(string $string)
use IterTools\Single;
$string = 'MickeyMouse';
$listOfCharacters = [];
foreach (Single::string($string) as $character) {
$listOfCharacters[] = $character;
}
// ['M', 'i', 'c', 'k', 'e', 'y', 'M', 'o', 'u', 's', 'e']
Return elements from the iterable as long as the predicate is true.
Stops iteration as soon as the predicate returns false, even if other elements later on would eventually return true (different from filterTrue).
Single::takeWhile(iterable $data, callable $predicate)
use IterTools\Single;
$prices = [0, 0, 5, 10, 0, 0, 9];
$isFree = fn ($price) => $price == 0;
foreach (Single::takeWhile($prices, $isFree) as $freePrice) {
print($freePrice);
}
// 0, 0
Count sequentially forever.
Infinite::count(int $start = 1, int $step = 1)
use IterTools\Infinite;
$start = 1;
$step = 1;
foreach (Infinite::count($start, $step) as $i) {
print($i);
}
// 1, 2, 3, 4, 5 ...
Cycle through the elements of a collection sequentially forever.
Infinite::cycle(iterable $iterable)
use IterTools\Infinite;
$hands = ['rock', 'paper', 'scissors'];
foreach (Infinite::cycle($hands) as $hand) {
RockPaperScissors::playHand($hand);
}
// rock, paper, scissors, rock, paper, scissors, ...
Repeat an item forever.
Infinite::repeat(mixed $item)
use IterTools\Infinite;
$dialogue = 'Are we there yet?';
foreach (Infinite::repeat($dialogue) as $repeated) {
print($repeated);
}
// 'Are we there yet?', 'Are we there yet?', 'Are we there yet?', ...
Generate random selections from an array of values.
Random::choice(array $items, int $repetitions)
use IterTools\Random;
$cards = ['Ace', 'King', 'Queen', 'Jack', 'Joker'];
$repetitions = 10;
foreach (Random::choice($cards, $repetitions) as $card) {
print($card);
}
// 'King', 'Jack', 'King', 'Ace', ... [random]
Generate random coin flips (0 or 1).
Random::coinFlip(int $repetitions)
use IterTools\Random;
$repetitions = 10;
foreach (Random::coinFlip($repetitions) as $coinFlip) {
print($coinFlip);
}
// 1, 0, 1, 1, 0, ... [random]
Generate random numbers (integers).
Random::number(int $min, int $max, int $repetitions)
use IterTools\Random;
$min = 1;
$max = 4;
$repetitions = 10;
foreach (Random::number($min, $max, $repetitions) as $number) {
print($number);
}
// 3, 2, 5, 5, 1, 2, ... [random]
Generate a random percentage between 0 and 1.
Random::percentage(int $repetitions)
use IterTools\Random;
$repetitions = 10;
foreach (Random::percentage($repetitions) as $percentage) {
print($percentage);
}
// 0.30205562629132, 0.59648594775233, ... [random]
Generate random rock-paper-scissors hands.
Random::rockPaperScissors(int $repetitions)
use IterTools\Random;
$repetitions = 10;
foreach (Random::rockPaperScissors($repetitions) as $rpsHand) {
print($rpsHand);
}
// 'paper', 'rock', 'rock', 'scissors', ... [random]
Returns a frequency distribution of the data.
Math::frequencies(iterable $data, bool $strict = true): \Generator
Defaults to strict type comparisons. Set strict to false for type coercion comparisons.
use IterTools\Math;
$grades = ['A', 'A', 'B', 'B', 'B', 'C'];
foreach (Math::frequencies($grades) as $grade => $frequency) {
print("$grade: $frequency" . \PHP_EOL);
}
// A: 2, B: 3, C: 1
Returns a relative frequency distribution of the data.
Math::relativeFrequencies(iterable $data, bool $strict = true): \Generator
Defaults to strict type comparisons. Set strict to false for type coercion comparisons.
use IterTools\Math;
$grades = ['A', 'A', 'B', 'B', 'B', 'C'];
foreach (Math::relativeFrequencies($grades) as $grade => $frequency) {
print("$grade: $frequency" . \PHP_EOL);
}
// A: 0.33, B: 0.5, C: 0.166
Accumulate the running average over a list of numbers.
Math::runningAverage(iterable $numbers, int|float $initialValue = null)
use IterTools\Math;
$grades = [100, 80, 80, 90, 85];
foreach (Math::runningAverage($grades) as $runningAverage) {
print($runningAverage);
}
// 100, 90, 86.667, 87.5, 87
Accumulate the running difference over a list of numbers.
Math::runningDifference(iterable $numbers, int|float $initialValue = null)
use IterTools\Math;
$credits = [1, 2, 3, 4, 5];
foreach (Math::runningDifference($credits) as $runningDifference) {
print($runningDifference);
}
// -1, -3, -6, -10, -15
Provide an optional initial value to lead off the running difference.
use IterTools\Math;
$dartsScores = [50, 50, 25, 50];
$startingScore = 501;
foreach (Math::runningDifference($dartsScores, $startingScore) as $runningScore) {
print($runningScore);
}
// 501, 451, 401, 376, 326
Accumulate the running maximum over a list of numbers.
Math::runningMax(iterable $numbers, int|float $initialValue = null)
use IterTools\Math;
$numbers = [1, 2, 1, 3, 5];
foreach (Math::runningMax($numbers) as $runningMax) {
print($runningMax);
}
// 1, 2, 2, 3, 5
Accumulate the running minimum over a list of numbers.
Math::runningMin(iterable $numbers, int|float $initialValue = null)
use IterTools\Math;
$numbers = [3, 4, 2, 5, 1];
foreach (Math::runningMin($numbers) as $runningMin) {
print($runningMin);
}
// 3, 3, 2, 2, 1
Accumulate the running product over a list of numbers.
Math::runningProduct(iterable $numbers, int|float $initialValue = null)
use IterTools\Math;
$numbers = [1, 2, 3, 4, 5];
foreach (Math::runningProduct($numbers) as $runningProduct) {
print($runningProduct);
}
// 1, 2, 6, 24, 120
Provide an optional initial value to lead off the running product.
use IterTools\Math;
$numbers = [1, 2, 3, 4, 5];
$initialValue = 5;
foreach (Math::runningProduct($numbers, $initialValue) as $runningProduct) {
print($runningProduct);
}
// 5, 5, 10, 30, 120, 600
Accumulate the running total over a list of numbers.
Math::runningTotal(iterable $numbers, int|float $initialValue = null)
use IterTools\Math;
$prices = [1, 2, 3, 4, 5];
foreach (Math::runningTotal($prices) as $runningTotal) {
print($runningTotal);
}
// 1, 3, 6, 10, 15
Provide an optional initial value to lead off the running total.
use IterTools\Math;
$prices = [1, 2, 3, 4, 5];
$initialValue = 5;
foreach (Math::runningTotal($prices, $initialValue) as $runningTotal) {
print($runningTotal);
}
// 5, 6, 8, 11, 15, 20
Filter out elements from the iterable only returning distinct elements.
Set::distinct(iterable $data, bool $strict = true)
Defaults to strict type comparisons. Set strict to false for type coercion comparisons.
use IterTools\Set;
$chessSet = ['rook', 'rook', 'knight', 'knight', 'bishop', 'bishop', 'king', 'queen', 'pawn', 'pawn', ... ];
foreach (Set::distinct($chessSet) as $chessPiece) {
print($chessPiece);
}
// rook, knight, bishop, king, queen, pawn
$mixedTypes = [1, '1', 2, '2', 3];
foreach (Set::distinct($mixedTypes, false) as $datum) {
print($datum);
}
// 1, 2, 3
Filter out elements from the iterable only returning distinct elements according to a custom comparator function.
Set::distinctBy(iterable $data, callable $compareBy)
use IterTools\Set;
$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' => '667788', 'name' => 'Street Fighter VI', 'console' => 'PC'],
];
$compareBy = fn ($sfTitle) => $sfTitle['name'];
$uniqueTitles = [];
foreach (Set::distinctBy($streetFighterConsoleReleases, $compareBy) as $sfTitle) {
$uniqueTitles[] = $sfTitle;
}
// Contains one SF3 3rd Strike entry and one SFVI entry.
Iterates intersection of iterables.
Set::intersection(iterable ...$iterables)
If input iterables produce duplicate items, then multiset intersection rules apply.
use IterTools\Set;
$chessPieces = ['rook', 'knight', 'bishop', 'queen', 'king', 'pawn'];
$shogiPieces = ['rook', 'knight', 'bishop' 'king', 'pawn', 'lance', 'gold general', 'silver general'];
foreach (Set::intersection($chessPieces, $shogiPieces) as $commonPiece) {
print($commonPiece);
}
// rook, knight, bishop, king, pawn
Iterates intersection of iterables using type coercion.
Set::intersectionCoercive(iterable ...$iterables)
If input iterables produce duplicate items, then multiset intersection rules apply.
use IterTools\Set;
$numbers = [1, 2, 3, 4, 5];
$numerics = ['1', '2', 3];
foreach (Set::intersectionCoercive($numbers, $numerics) as $commonNumber) {
print($commonNumber);
}
// 1, 2, 3
Iterates M-partial intersection of iterables.
Set::partialIntersection(int $minIntersectionCount, iterable ...$iterables)
use IterTools\Set;
$staticallyTyped = ['c++', 'java', 'c#', 'go', 'haskell'];
$dynamicallyTyped = ['php', 'python', 'javascript', 'typescript'];
$supportsInterfaces = ['php', 'java', 'c#', 'typescript'];
foreach (Set::partialIntersection(2, $staticallyTyped, $dynamicallyTyped, $supportsInterfaces) as $language) {
print($language);
}
// c++, java, c#, go, php
Iterates M-partial intersection of iterables using type coercion.
Set::partialIntersectionCoercive(int $minIntersectionCount, iterable ...$iterables)
use IterTools\Set;
$set1 = [1, 2, 3],
$set2 = ['2', '3', 4, 5],
$set3 = [1, '2'],
foreach (Set::partialIntersectionCoercive(2, $set1, $set2, $set3) as $partiallyCommonNumber) {
print($partiallyCommonNumber);
}
// 1, 2, 3
Iterates the symmetric difference of iterables.
Set::symmetricDifference(iterable ...$iterables)
If input iterables produce duplicate items, then multiset difference rules apply.
use IterTools\Set;
$a = [1, 2, 3, 4, 7];
$b = ['1', 2, 3, 5, 8];
$c = [1, 2, 3, 6, 9];
foreach (Set::symmetricDifference($a, $b, $c) as $item) {
print($item);
}
// 1, 4, 5, 6, 7, 8, 9
Iterates the symmetric difference of iterables with type coercion.
Set::symmetricDifferenceCoercive(iterable ...$iterables)
If input iterables produce duplicate items, then multiset difference rules apply.
use IterTools\Set;
$a = [1, 2, 3, 4, 7];
$b = ['1', 2, 3, 5, 8];
$c = [1, 2, 3, 6, 9];
foreach (Set::symmetricDifferenceCoercive($a, $b, $c) as $item) {
print($item);
}
// 4, 5, 6, 7, 8, 9
Iterates the union of iterables.
Set::union(iterable ...$iterables)
If input iterables produce duplicate items, then multiset union rules apply.
use IterTools\Set;
$a = [1, 2, 3];
$b = [3, 4];
$c = [1, 2, 3, 6, 7];
foreach (Set::union($a, $b, $c) as $item) {
print($item);
}
//1, 2, 3, 4, 6, 7
Iterates the union of iterables with type coercion.
Set::unionCoercive(iterable ...$iterables)
If input iterables produce duplicate items, then multiset union rules apply.
use IterTools\Set;
$a = ['1', 2, 3];
$b = [3, 4];
$c = [1, 2, 3, 6, 7];
foreach (Set::unionCoercive($a, $b, $c) as $item) {
print($item);
}
//1, 2, 3, 4, 6, 7
Iterate the collection sorted while maintaining the associative key index relations.
Sort::sort(iterable $data, callable $comparator = null)
Uses default sorting if optional comparator function not provided.
use IterTools\Single;
$worldPopulations = [
'China' => 1_439_323_776,
'India' => 1_380_004_385,
'Indonesia' => 273_523_615,
'Pakistan' => 220_892_340,
'USA' => 331_002_651,
];
foreach (Sort::sort($worldPopulations) as $country => $population) {
print("$country: $population" . \PHP_EOL);
}
// Pakistan: 220,892,340
// Indonesia: 273,523,615
// USA: 331,002,651
// India: 1,380,004,385
// China: 1,439,323,776
Iterate the collection sorted.
Sort::sort(iterable $data, callable $comparator = null)
Uses default sorting if optional comparator function not provided.
use IterTools\Single;
$data = [3, 4, 5, 9, 8, 7, 1, 6, 2];
foreach (Sort::sort($data) as $datum) {
print($datum);
}
// 1, 2, 3, 4, 5, 6, 7, 8, 9
Iterate the lines of a CSV file.
File::readCsv(resource $fileHandle, string $separator = ',', string $enclosure = '"', string $escape = '\\')
use IterTools\File;
$fileHandle = \fopen('path/to/file.csv', 'r');
foreach (File::readCsv($fileHandle) as $row) {
print_r($row);
}
// Each column field is an element of the array
Iterate the lines of a file.
File::readLines(resource $fileHandle)
use IterTools\File;
$fileHandle = \fopen('path/to/file.txt', 'r');
foreach (File::readLines($fileHandle) as $line) {
print($line);
}
Return several independent (duplicated) iterators from a single iterable.
Transform::tee(iterable $data, int $count): array
use IterTools\Transform;
$daysOfWeek = ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'];
$count = 3;
[$week1, $week2, $week3] = Transform::tee($data, $count);
// Each $week contains iterator containing ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
Transforms any iterable to an array.
Transform::toArray(iterable $data): array
use IterTools\Transform;
$iterator = new \ArrayIterator([1, 2, 3, 4, 5]);
$array = Transform::toArray($iterator);
Transforms any iterable to an associative array.
Transform::toAssociativeArray(iterable $data, callable $keyFunc = null, callable $valueFunc = null): array
use IterTools\Transform;
$messages = ['message 1', 'message 2', 'message 3'];
$keyFunc = fn ($msg) => \md5($msg);
$valueFunc = fn ($msg) => strtoupper($msg);
$associativeArray = Transform::toAssociativeArray($messages, $keyFunc, $valueFunc);
// [
// '1db65a6a0a818fd39655b95e33ada11d' => 'MESSAGE 1',
// '83b2330607fe8f817ce6d24249dea373' => 'MESSAGE 2',
// '037805d3ad7b10c5b8425427b516b5ce' => 'MESSAGE 3',
// ]
Transforms any iterable to an iterator.
Transform::toArray(iterable $data): array
use IterTools\Transform;
$array = [1, 2, 3, 4, 5];
$iterator = Transform::toIterator($array);
Returns true if all elements match the predicate function.
Summary::allMatch(iterable $data, callable $predicate): bool
use IterTools\Summary;
$finalFantasyNumbers = [4, 5, 6];
$isOnSuperNintendo = fn ($ff) => $ff >= 4 && $ff <= 6;
$boolean = Summary::allMatch($finalFantasyNumbers, $isOnSuperNintendo);
// true
$isOnPlaystation = fn ($ff) => $ff >= 7 && $ff <= 9;
$boolean = Summary::allMatch($finalFantasyNumbers, $isOnPlaystation);
// false
Returns true if all elements are unique.
Summary::allUnique(iterable $data, bool $strict = true): bool
Defaults to strict type comparisons. Set strict to false for type coercion comparisons.
use IterTools\Summary;
$items = ['fingerprints', 'snowflakes', 'eyes', 'DNA']
$boolean = Summary::allUnique($items);
// true
Returns true if any element matches the predicate function.
Summary::anyMatch(iterable $data, callable $predicate): bool
use IterTools\Summary;
$answers = ['fish', 'towel', 42, "don't panic"];
$isUltimateAnswer = fn ($a) => a == 42;
$boolean = Summary::anyMatch($answers, $isUltimateAnswer);
// true
Returns true if all iterables are permutations of each other.
Summary::arePermutations(iterable ...$iterables): bool
use IterTools\Summary;
$iter = ['i', 't', 'e', 'r'];
$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 = Summary::arePermutations($iter, $rite, $reit, $tier, $tire, $trie);
// true
Returns true if all iterables are permutations of each other with type coercion.
Summary::arePermutationsCoercive(iterable ...$iterables): bool
use IterTools\Summary;
$set1 = [1, 2.0, '3'];
$set2 = [2.0, '1', 3];
$set3 = [3, 2, 1];
$boolean = Summary::arePermutationsCoercive($set1, $set2, $set3);
// true
Returns true if exactly n items are true according to a predicate function.
Summary::exactlyN(iterable $data, int $n, callable $predicate): bool
use IterTools\Summary;
$twoTruthsAndALie = [true, true, false];
$n = 2;
$boolean = Summary::exactlyN($twoTruthsAndALie, $n);
// true
$ages = [18, 21, 24, 54];
$n = 4;
$predicate = fn ($age) => $age >= 21;
$boolean = Summary::exactlyN($ages, $n, $predicate);
// false
Returns true if the iterable is empty having no items.
Summary::isEmpty(iterable $data): bool
use IterTools\Summary;
$data = []
$boolean = Summary::isEmpty($data);
// true
Returns true if all elements of given collection that satisfy the predicate appear before all elements that don't.
Summary::isPartitioned(iterable $data, callable $predicate = null): bool
use IterTools\Summary;
$numbers = [0, 2, 4, 1, 3, 5];
$evensBeforeOdds = fn ($item) => $item % 2 === 0;
$boolean = Summary::isPartitioned($numbers, $evensBeforeOdds);
Returns true if elements are sorted, otherwise false.
Summary::isSorted(iterable $data): bool
use IterTools\Summary;
$numbers = [1, 2, 3, 4, 5];
$boolean = Summary::isSorted($numbers);
// true
$numbers = [3, 2, 3, 4, 5];
$boolean = Summary::isSorted($numbers);
// false
Returns true if elements are reverse sorted, otherwise false.
Summary::isReversed(iterable $data): bool
use IterTools\Summary;
$numbers = [5, 4, 3, 2, 1];
$boolean = Summary::isReversed($numbers);
// true
$numbers = [1, 4, 3, 2, 1];
$boolean = Summary::isReversed($numbers);
// false
Returns true if no element matches the predicate function.
Summary::noneMatch(iterable $data, callable $predicate): bool
use IterTools\Summary;
$grades = [45, 50, 61, 0];
$isPassingGrade = fn ($grade) => $grade >= 70;
$boolean = Summary::noneMatch($grades, $isPassingGrade);
// true
Returns true if all given collections are the same.
For single iterable or empty iterables list returns true.
Summary::same(iterable ...$iterables): bool
use IterTools\Summary;
$cocaColaIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid'];
$pepsiIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid'];
$boolean = Summary::same($cocaColaIngredients, $pepsiIngredients);
// true
$cocaColaIngredients = ['carbonated water', 'sugar', 'caramel color', 'phosphoric acid'];
$spriteIngredients = ['carbonated water', 'sugar', 'citric acid', 'lemon lime flavorings'];
$boolean = Summary::same($cocaColaIngredients, $spriteIngredients);
// false
Returns true if all given collections have the same lengths.
For single iterable or empty iterables list returns true.
Summary::sameCount(iterable ...$iterables): bool
use IterTools\Summary;
$prequels = ['Phantom Menace', 'Attack of the Clones', 'Revenge of the Sith'];
$originals = ['A New Hope', 'Empire Strikes Back', 'Return of the Jedi'];
$sequels = ['The Force Awakens', 'The Last Jedi', 'The Rise of Skywalker'];
$boolean = Summary::sameCount($prequels, $originals, $sequels);
// true
$batmanMovies = ['Batman Begins', 'The Dark Knight', 'The Dark Knight Rises'];
$matrixMovies = ['The Matrix', 'The Matrix Reloaded', 'The Matrix Revolutions', 'The Matrix Resurrections'];
$result = Summary::sameCount($batmanMovies, $matrixMovies);
// false
Reduces to the mean average.
Returns null if collection is empty.
Reduce::toAverage(iterable $data): float
use IterTools\Reduce;
$grades = [100, 90, 95, 85, 94];
$finalGrade = Reduce::toAverage($numbers);
// 92.8
Reduces iterable to its length.
Reduce::toCount(iterable $data): int
use IterTools\Reduce;
$someIterable = ImportantThing::getCollectionAsIterable();
$length = Reduce::toCount($someIterable);
// 3
Reduces iterable to its first element.
Reduce::toFirst(iterable $data): mixed
Throws \LengthException
if collection is empty.
use IterTools\Reduce;
$medals = ['gold', 'silver', 'bronze'];
$first = Reduce::toFirst($medals);
// gold
Reduces iterable to its first and last elements.
Reduce::toFirstAndLast(iterable $data): array{mixed, mixed}
Throws \LengthException
if collection is empty.
use IterTools\Reduce;
$weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
$firstAndLast = Reduce::toFirstAndLast($weekdays);
// [Monday, Friday]
Reduces iterable to its last element.
Reduce::toLast(iterable $data): mixed
Throws \LengthException
if collection is empty.
use IterTools\Reduce;
$gnomesThreePhasePlan = ['Collect underpants', '?', 'Profit'];
$lastPhase = Reduce::toLast($gnomesThreePhasePlan);
// Profit
Reduces to the max value.
Reduce::toMax(iterable $data, callable $compareBy = null): mixed|null
$compareBy
must return comparable value.$compareBy
is not provided then items of given collection must be comparable.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
// ];
Reduces to the min value.
Reduce::toMin(iterable $data, callable $compareBy = null): mixed|null
$compareBy
must return comparable value.$compareBy
is not provided then items of given collection must be comparable.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
// ]
Reduces to array of its upper and lower bounds (max and min).
Reduce::toMinMax(iterable $numbers, callable $compareBy = null): array
$compareBy
must return comparable value.$compareBy
is not provided then items of given collection must be comparable.[null, null]
if given collection is empty.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
// ],
// ]
Reduces to value at the nth position.
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
Reduces to the product of its elements.
Returns null if collection is empty.
Reduce::toProduct(iterable $data): number|null
use IterTools\Reduce;
$primeFactors = [5, 2, 2];
$number = Reduce::toProduct($primeFactors);
// 20
Reduces given collection to a random value within it.
Reduce::toRandomValue(iterable $data): mixed
use IterTools\Reduce;
$sfWakeupOptions = ['mid', 'low', 'overhead', 'throw', 'meaty'];
$wakeupOption = Reduce::toRandomValue($sfWakeupOptions);
// e.g., throw
Reduces given collection to its range (difference between max and min).
Reduce::toRange(iterable $numbers): int|float
Returns 0
if iterable source is empty.
use IterTools\Reduce;
$grades = [100, 90, 80, 85, 95];
$range = Reduce::toRange($numbers);
// 20
Reduces to a string joining all elements.
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!
Reduces to the sum of its elements.
Reduce::toSum(iterable $data): number
use IterTools\Reduce;
$parts = [10, 20, 30];
$sum = Reduce::toSum($parts);
// 60
Reduce elements to a single value using reducer function.
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
Streams provide a fluent interface to transform arrays and iterables through a pipeline of operations.
Streams are made up of:
$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]
->filter(fn ($x) => $x < 10) // [1, 4, 9]
->toSum(); // 14
foreach
loop.$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]
->filter(fn ($x) => $x < 10); // [1, 4, 9]
foreach ($result as $item) {
// 1, 4, 9
}
Creates stream from an iterable.
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
Creates stream of n random coin flips.
Stream::ofCoinFlips(int $repetitions): Stream
use IterTools\Stream;
$result = Stream::ofCoinFlips(10)
->filterTrue()
->toCount();
// 5 (random)
Creates a stream of rows of a CSV file.
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();
Creates stream of nothing.
Stream::ofEmpty(): Stream
use IterTools\Stream;
$result = Stream::ofEmpty()
->chainWith([1, 2, 3])
->toArray();
// 1, 2, 3
Creates a stream of lines of a file.
Stream::ofFileLines(resource $fileHandle): Stream
use IterTools\Stream;
$fileHandle = \fopen('path/to/file.txt', 'r');
$result = Stream::of($fileHandle)
->map('strtoupper');
->toArray();
Creates stream of random selections from an array of values.
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)
Creates stream of random numbers (integers).
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)
Creates stream of random percentages between 0 and 1.
Stream::ofRandomPercentage(int $repetitions): Stream
use IterTools\Stream;
$stream = Stream::ofRandomPercentage(3)
->toArray();
// 0.8012566976245, 0.81237281724151, 0.61676896329459 [random]
Creates stream of a range of numbers.
Stream::ofRange(int|float $start, int|float $end, int|float $step = 1): Stream
use IterTools\Stream;
$numbers = Stream::ofRange(0, 5)
->toArray();
// 0, 1, 2, 3, 4, 5
Creates stream of rock-paper-scissors hands.
Stream::ofRockPaperScissors(int $repetitions): Stream
use IterTools\Stream;
$rps = Stream::ofRockPaperScissors(5)
->toArray();
// 'paper', 'rock', 'rock', 'scissors', 'paper' [random]
Sorts the stream, maintaining keys.
$stream->asort(callable $comparator = null)
If comparator is not provided, the elements of the iterable source must be comparable.
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,
Return a stream chaining additional sources together into a single consecutive stream.
$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
Compress to a new stream by filtering out data that is not selected.
$stream->compress(iterable $selectors): Stream
Selectors indicate which data. True value selects item. False value filters out data.
use IterTools\Stream;
$input = [1, 2, 3];
$result = Stream::of($input)
->compress([0, 1, 1])
->toArray();
// 2, 3
Compress to a new stream by filtering out keys that are not selected.
$stream->compressAssociative(array $keys): Stream
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',
Return a stream consisting of chunks of elements from the stream.
$stream->chunkwise(int $chunkSize): Stream
Chunk size must be at least 1.
use IterTools\Stream;
$friends = ['Ross', 'Rachel', 'Chandler', 'Monica', 'Joey'];
$result = Stream::of($friends)
->chunkwise(2)
->toArray();
// ['Ross', 'Rachel'], ['Chandler', 'Monica'], ['Joey']
Return a stream consisting of overlapping chunks of elements from the stream.
$stream->chunkwiseOverlap(int $chunkSize, int $overlapSize, bool $includeIncompleteTail = true): Stream
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]
Return a stream filtering out elements from the stream only returning distinct elements.
$stream->distinct(bool $strict = true): Stream
Defaults to strict type comparisons. Set strict to false for type coercion comparisons.
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
Return a stream filtering out elements from the stream only returning distinct elements according to a custom comparator function.
$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();
// Contains one SF3 3rd Strike entry and one SFVI entry
Drop elements from the stream while the predicate function is true.
$stream->dropWhile(callable $predicate): Stream
Once the predicate function returns false once, all remaining elements are returned.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5]
$result = Stream::of($input)
->dropWhile(fn ($value) => $value < 3)
->toArray();
// 3, 4, 5
Filter out elements from the stream only keeping elements where there predicate function is true.
$stream->filter(callable $predicate): Stream
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($input)
->filter(fn ($value) => $value > 0)
->toArray();
// 1, 2, 3
Filter out elements from the stream only keeping elements that are truthy.
$stream->filterTrue(): Stream
use IterTools\Stream;
$input = [0, 1, 2, 3, 0, 4];
$result = Stream::of($input)
->filterTrue()
->toArray();
// 1, 2, 3, 4
Filter out elements from the stream only keeping elements that are falsy.
$stream->filterFalse(): Stream
use IterTools\Stream;
$input = [0, 1, 2, 3, 0, 4];
$result = Stream::of($input)
->filterFalse()
->toArray();
// 0, 0
Filter out elements from stream only keeping elements where the predicate function on the keys are true.
$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
Map a function onto the elements of the stream and flatten the results.
$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]
Flatten a multidimensional stream.
$stream->flatten(int $dimensions = 1): Stream
$data = [1, [2, 3], [4, 5]];
$result = Stream::of($data)
->flatten($mapper)
->toArray();
// [1, 2, 3, 4, 5]
Frequency distribution of the stream elements.
$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]
Return a stream grouping by a common data element.
$stream->groupBy(callable $groupKeyFunction, callable $itemKeyFunction = null): Stream
$groupKeyFunction
determines the key to group elements by.$itemKeyFunction
allows custom indexes within each group member.use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$groups = Stream::of($input)
->groupBy(fn ($item) => $item > 0 ? 'positive' : 'negative');
foreach ($groups as $group => $item) {
// 'positive' => [1, 2, 3], 'negative' => [-1, -2, -3]
}
Return a stream cycling through the elements of stream sequentially forever.
$stream->infiniteCycle(): Stream
use IterTools\Stream;
$input = [1, 2, 3];
$result = Stream::of($input)
->infiniteCycle()
->print();
// 1, 2, 3, 1, 2, 3, ...
Return a stream intersecting the stream with the input iterables.
$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
Return a stream intersecting the stream with the input iterables using type coercion.
$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'
Return a stream up to a limit.
Stops even if more data available if limit reached.
$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)
Return a stream containing the result of mapping a function onto each element of the stream.
$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
Return a stream consisting of pairs of elements from the stream.
$stream->pairwise(): Stream
Returns empty stream if given collection contains less than 2 elements.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$stream = Stream::of($input)
->pairwise()
->toArray();
// [1, 2], [2, 3], [3, 4], [4, 5]
Return a stream partially intersecting the stream with the input iterables.
$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
Return a stream partially intersecting the stream with the input iterables using type coercion.
$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'
Return a new stream of key-value elements reindexed by the key indexer function.
$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 frequency distribution of the stream elements.
$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
Reverse the elements of a stream.
$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
Return a stream accumulating the running average (mean) over the stream.
$stream->runningAverage(int|float|null $initialValue = null): Stream
use IterTools\Stream;
$input = [1, 3, 5];
$result = Stream::of($input)
->runningAverage()
->toArray();
// 1, 2, 3
Return a stream accumulating the running difference over the stream.
$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
Return a stream accumulating the running max over the stream.
$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
Return a stream accumulating the running min over the stream.
$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
Return a stream accumulating the running product over the stream.
$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
Return a stream accumulating the running total over the stream.
$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 some elements of the stream.
$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'
Extract a slice of the stream.
$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]
Sorts the stream.
$stream->sort(callable $comparator = null)
If comparator is not provided, the elements of the iterable source must be comparable.
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
Return a stream of the symmetric difference of the stream and the given iterables.
$stream->symmetricDifferenceWith(iterable ...$iterables): Stream
Note: If input iterables produce duplicate items, then multiset intersection rules apply.
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
Return a stream of the symmetric difference of the stream and the given iterables using type coercion.
$stream->symmetricDifferenceCoerciveWith(iterable ...$iterables): Stream
Note: If input iterables produce duplicate items, then multiset intersection rules apply.
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
Keep elements from the stream as long as the predicate is true.
$stream->takeWhile(callable $predicate): Stream
If no predicate is provided, the boolean value of the data is used.
use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($input)
->takeWhile(fn ($value) => abs($value) < 3)
->toArray();
// 1, -1, 2, -2
Return a stream consisting of the union of the stream and the input iterables.
$stream->unionWith(iterable ...$iterables): Stream
Note: If input iterables produce duplicate items, then multiset union rules apply.
use IterTools\Stream;
$input = [1, 2, 3];
$stream = Stream::of($input)
->unionWith([3, 4, 5, 6])
->toArray();
// [1, 2, 3, 4, 5, 6]
Return a stream consisting of the union of the stream and the input iterables using type coercion.
$stream->unionCoerciveWith(iterable ...$iterables): Stream
Note: If input iterables produce duplicate items, then multiset union rules apply.
use IterTools\Stream;
$input = [1, 2, 3];
$stream = Stream::of($input)
->unionCoerciveWith(['3', 4, 5, 6])
->toArray();
// [1, 2, 3, 4, 5, 6]
Return a stream consisting of multiple iterable collections streamed simultaneously.
$stream->zipWith(iterable ...$iterables): Stream
For uneven lengths, iterations stops when the shortest iterable is exhausted.
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]
Return a stream consisting of multiple iterable collections, using a default filler value if lengths no equal.
$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, ?]
}
Return a stream consisting of multiple iterable collections of equal lengths streamed simultaneously.
$stream->zipEqualWith(iterable ...$iterables): Stream
Works like Stream::zipWith()
method but throws \LengthException if lengths not equal,
i.e., at least one iterator ends before the others.
use IterTools\Stream;
$input = [1, 2, 3];
$stream = Stream::of($input)
->zipEqualWith([4, 5, 6])
->zipEqualWith([7, 8, 9]);
foreach ($stream as $zipped) {
// [1, 4, 7], [2, 5, 8], [3, 6, 9]
}
Return a stream consisting of multiple iterable collections streamed simultaneously.
$stream->zipLongestWith(iterable ...$iterables): Stream
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$stream = Stream::of($input)
->zipLongestWith([4, 5, 6])
->zipLongestWith([7, 8, 9, 10]);
foreach ($stream as $zipped) {
// [1, 4, 7], [2, 5, 8], [3, 6, 9], [4, null, 10], [null, null, 5]
}
Returns true if all elements match the predicate function.
$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
Returns true if all elements are unique.
$stream->allUnique(bool $strict = true): bool
Defaults to strict type comparisons. Set strict to false for type coercion comparisons.
use IterTools\Summary;
$items = ['fingerprints', 'snowflakes', 'eyes', 'DNA']
$boolean = Stream::of($items)
->allUnique();
// true
Returns true if any element matches the predicate function.
$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
Returns true if all iterables are permutations with stream.
$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
Returns true if all iterables are permutations with stream with type coercion.
$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
Returns true if exactly n items are true according to a predicate function.
$stream->exactlyN(int $n, callable $predicate = null): bool
use IterTools\Summary;
$twoTruthsAndALie = [true, true, false];
$n = 2;
$boolean = Stream::of($twoTruthsAndALie)->exactlyN($n);
// true
Returns true if the stream is empty having no items.
$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
Returns true if all elements of given collection that satisfy the predicate appear before all elements that don't.
$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
Returns true if iterable source is sorted in ascending order; otherwise false.
$stream->isSorted(): bool
Items of iterable source must be comparable.
Returns true if iterable source is empty or has only one element.
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
Returns true if iterable source is sorted in reverse descending order; otherwise false.
$stream->isReversed(): bool
Items of iterable source must be comparable.
Returns true if iterable source is empty or has only one element.
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
Returns true if no element matches the predicate function.
$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
Returns true if iterable source and all given collections are the same.
$stream->sameWith(iterable ...$iterables): bool
For empty iterables list returns true.
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
Returns true if iterable source and all given collections have the same lengths.
$stream->sameCountWith(iterable ...$iterables): bool
For empty iterables list returns true.
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
Reduces iterable source to the mean average of its items.
$stream->toAverage(): mixed
Returns null if iterable source is empty.
use IterTools\Stream;
$input = [2, 4, 6, 8];
$result = Stream::of($iterable)
->toAverage();
// 5
Reduces iterable source to its length.
$stream->toCount(): mixed
use IterTools\Stream;
$input = [10, 20, 30, 40, 50];
$result = Stream::of($iterable)
->toCount();
// 5
Reduces iterable source to its first element.
$stream->toFirst(): mixed
Throws \LengthException
if iterable source is empty.
use IterTools\Stream;
$input = [10, 20, 30];
$result = Stream::of($input)
->toFirst();
// 10
Reduces iterable source to its first and last elements.
$stream->toFirstAndLast(): array{mixed, mixed}
Throws \LengthException
if iterable source is empty.
use IterTools\Stream;
$input = [10, 20, 30];
$result = Stream::of($input)
->toFirstAndLast();
// [10, 30]
Reduces iterable source to its last element.
$stream->toLast(): mixed
Throws \LengthException
if iterable source is empty.
use IterTools\Stream;
$input = [10, 20, 30];
$result = Stream::of($input)
->toLast();
// 30
Reduces iterable source to its max value.
$stream->toMax(callable $compareBy = null): mixed
$compareBy
must return comparable value.$compareBy
is not provided then items of given collection must be comparable.use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($iterable)
->toMax();
// 3
Reduces iterable source to its min value.
$stream->toMin(callable $compareBy = null): mixed
$compareBy
must return comparable value.$compareBy
is not provided then items of given collection must be comparable.use IterTools\Stream;
$input = [1, -1, 2, -2, 3, -3];
$result = Stream::of($iterable)
->toMin();
// -3
Reduces stream to array of its upper and lower bounds (max and min).
$stream->toMinMax(callable $compareBy = null): array
$compareBy
must return comparable value.$compareBy
is not provided then items of given collection must be comparable.[null, null]
if given collection is empty.use IterTools\Stream;
$numbers = [1, 2, 7, -1, -2, -3];
[$min, $max] = Stream::of($numbers)
->toMinMax();
// [-3, 7]
Reduces stream to value at the nth position.
$stream->toNth(int $position): mixed
Returns null if iterable source is empty.
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
Reduces stream to the product of its items.
$stream->toProduct(): mixed
Returns null if iterable source is empty.
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($iterable)
->toProduct();
// 120
Reduces stream to a random value within it.
$stream->toRandomValue(): mixed
use IterTools\Stream;
$rpsHands = ['rock', 'paper', 'scissors']
$range = Stream::of($numbers)
->map('strtoupper')
->toRandomValue();
// e.g., rock
Reduces stream to its range (difference between max and min).
$stream->toRange(): int|float
Returns 0
if iterable source is empty.
use IterTools\Stream;
$grades = [100, 90, 80, 85, 95];
$range = Stream::of($numbers)
->toRange();
// 20
Reduces to a string joining all elements.
$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!
Reduces iterable source to the sum of its items.
$stream->toSum(): mixed
use IterTools\Stream;
$input = [1, 2, 3, 4, 5];
$result = Stream::of($iterable)
->toSum();
// 15
Reduces iterable source like array_reduce() function.
But unlike array_reduce()
, it works with all iterable
types.
$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
Returns an array of stream elements.
$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]
Returns a key-value map of stream elements.
$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, ... ]
Return several independent (duplicated) streams.
$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);
// Each $weekStream contains ['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun']
Perform an action via a callable on each item in the stream.
$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
// ...
Prints each item in the stream.
$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!
Prints each item in the stream on its own line.
$stream->println(): void
use IterTools\Stream;
$words = ['IterTools', 'PHP', 'v1.0'];
Stream::of($words)->printLn();
// IterTools
// PHP
// v1.0
Write the contents of the stream to a CSV file.
$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
Write the contents of the stream to a 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 at each element between other Stream operations to do some action without modifying the stream.
$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 at the entire stream between other Stream operations to do some action without modifying the stream.
$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 at each element between other Stream operations to print each item without modifying the stream.
$stream->peekPrint(string $separator = '', string $prefix = '', string $suffix = ''): void
use IterTools\Stream;
Stream::of(['some', 'items'])
->map('strtoupper')
->peekPrint()
->foreach($someComplexCallable);
Peek at each element between other Stream operations to print_r
each item without modifying the stream.
$stream->peekPrintR(callable $callback): void
use IterTools\Stream;
Stream::of(['some', 'items'])
->map('strtoupper')
->peekPrintR()
->foreach($someComplexCallable);
print_r
each item in the stream.
$stream->printR(): void
use IterTools\Stream;
$items = [$string, $array, $object];
Stream::of($words)->printR();
// print_r output
var_dump
each item in the stream.
$stream->varDump(): void
use IterTools\Stream;
$items = [$string, $array, $object];
Stream::of($words)->varDump();
// var_dump output
IterTools can be combined to create new iterable compositions.
use IterTools\Multi;
use IterTools\Single;
$letters = 'ABCDEFGHI';
$numbers = '123456789';
foreach (Multi::zip(Single::string($letters), Single::string($numbers)) as [$letter, $number]) {
$battleshipMove = new BattleshipMove($letter, $number)
}
// A1, B2, C3
use IterTools\Multi;
use IterTools\Single;
$letters = 'abc';
$numbers = '123';
foreach (Multi::chain(Single::string($letters), Single::string($numbers)) as $character) {
print($character);
}
// a, b, c, 1, 2, 3
When there is an option, the default will do strict type comparisons:
When type coercion (non-strict types) is available and enabled via optional flag:
IterTools PHP conforms to the following standards:
IterTools PHP is licensed under the MIT License.
IterTools functionality is not limited to PHP and Python. Other languages have similar libraries. Familiar functionality is available when working in other languages.