Inspired by Python—designed for PHP.
IterTools makes you an iteration superstar by providing two types of tools:
- Loop iteration tools
- Stream iteration 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(); // 14All functions work on iterable collections:
array(type)Generator(type)Iterator(interface)Traversable(interface)
Add the library to your composer.json file in your project:
{
"require": {
"markrogoyski/itertools-php": "2.*"
}
}Use composer to install the library:
$ composer installComposer 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:
$ composer require markrogoyski/itertools-php:2.*
- PHP 8.2+
- (For PHP 7.4–8.1, use v1.9)
| 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) |
difference |
Difference of iterables | Set::difference($a, ...$iterables) |
differenceCoercive |
Difference with type coercion | Set::differenceCoercive($a, ...$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) |
intersectionCoerciveWith |
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) |
partialIntersectionCoerciveWith |
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]) |
differenceWith |
Difference of iterable source and given iterables | $stream->differenceWith(...$iterables) |
differenceCoerciveWith |
Difference of iterable source and given iterables with type coercion | $stream->differenceCoerciveWith(...$iterables) |
symmetricDifferenceWith |
Symmetric difference of iterable source and given iterables | $stream->symmetricDifferenceWith(...$iterables) |
symmetricDifferenceCoerciveWith |
Symmetric difference of iterable source and given iterables with type coercion | $stream->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() |
Full documentation with detailed descriptions, signatures, and code examples for each function.
- Multi Iteration — Chain, Zip, ZipEqual, ZipFilled, ZipLongest
- Single Iteration — Chunkwise, Compress, Filter, Map, Flatten, GroupBy, and more
- Infinite Iteration — Count, Cycle, Repeat
- Random Iteration — Choice, CoinFlip, Number, Percentage, RockPaperScissors
- Math Iteration — Frequencies, Running Average/Difference/Max/Min/Product/Total
- Set and Multiset Iteration — Distinct, Intersection, Difference, Symmetric Difference, Union
- Sort Iteration — ASort, Sort
- File Iteration — ReadCsv, ReadLines
- Transform Iteration — Tee, ToArray, ToAssociativeArray, ToIterator
- Summary — AllMatch, AnyMatch, IsEmpty, IsSorted, and more
- Reduce — ToAverage, ToSum, ToMin, ToMax, ToString, and more
- Stream — Sources, operations, terminal operations, and debug tools
All functions work on iterable collections:
array(type)Generator(type)Iterator(interface)Traversable(interface)
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, C3use 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, 3When there is an option, the default will do strict type comparisons:
- scalars: compares strictly by type
- objects: always treats different instances as not equal to each other
- arrays: compares serialized
When type coercion (non-strict types) is available and enabled via optional flag:
- scalars: compares by value via type juggling
- objects: compares serialized
- arrays: compares serialized
IterTools PHP conforms to the following standards:
- PSR-1 - Basic coding standard (http://www.php-fig.org/psr/psr-1/)
- PSR-4 - Autoloader (http://www.php-fig.org/psr/psr-4/)
- PSR-12 - Extended coding style guide (http://www.php-fig.org/psr/psr-12/)
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.
- IterTools TypeScript/Javascript
- IterTools Python: The original!
