Working with Iterators
Nette\Utils\Iterables is a static class with functions for working with iterators. Its counterpart for arrays is Nette\Utils\Arrays.
Installation:
composer require nette/utils
All examples assume the following alias is created:
use Nette\Utils\Iterables;
contains (iterable $iterable, $value): bool
Searches for a given value within an iterator. Uses strict comparison (===
) to check for a match. Returns
true
if the value is found, otherwise false
.
Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true
Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false
This method is useful when you need to quickly determine if a specific value exists in an iterator without manually iterating through all elements.
containsKey (iterable $iterable, $key): bool
Searches for a given key within an iterator. Uses strict comparison (===
) to check for a match. Returns
true
if the key is found, otherwise false
.
Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true
Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false
every (iterable $iterable, callable $predicate): bool
Checks if all elements of the iterator satisfy the condition defined in $predicate
. The callback
$predicate
has the signature function ($value, $key, iterable $iterable): bool
and must return
true
for every element for the every()
method to return true
.
$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
$isBelowThreshold = fn($value) => $value < 40;
$res = Iterables::every($iterator, $isBelowThreshold); // true
This method is useful for verifying that all elements in a collection meet a certain condition, for example, whether all numbers are less than a specific value.
filter (iterable $iterable, callable $predicate): Generator
Creates a new iterator containing only those elements from the original iterator that satisfy the condition defined in
$predicate
. The callback $predicate
has the signature
function ($value, $key, iterable $iterable): bool
and must return true
for elements that should be
retained.
$iterator = new ArrayIterator([1, 2, 3]);
$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
// 1, 2
The method uses a generator, meaning filtering occurs incrementally as you iterate through the result. This is memory-efficient and allows processing very large collections. If you don't iterate through all elements of the resulting iterator, you save computational power because not all elements of the original iterator are processed.
first (iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed
Returns the first element of the iterator. If $predicate
is provided, it returns the first element that satisfies
the condition. The callback $predicate
has the signature
function ($value, $key, iterable $iterable): bool
. If no matching element is found, the $else
callback
(if provided) is called, and its result is returned. If $else
is not provided, null
is returned.
Iterables::first(new ArrayIterator([1, 2, 3])); // 1
Iterables::first(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 3
Iterables::first(new ArrayIterator([])); // null
Iterables::first(new ArrayIterator([]), else: fn() => false); // false
This method is useful when you need to quickly get the first element of a collection, or the first element satisfying a specific condition, without manually iterating through the entire collection.
firstKey (iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed
Returns the key of the first element of the iterator. If $predicate
is provided, it returns the key of the first
element that satisfies the condition. The callback $predicate
has the signature
function ($value, $key, iterable $iterable): bool
. If no matching element is found, the $else
callback
(if provided) is called, and its result is returned. If $else
is not provided, null
is returned.
Iterables::firstKey(new ArrayIterator([1, 2, 3])); // 0
Iterables::firstKey(new ArrayIterator([1, 2, 3]), fn($v) => $v > 2); // 2
Iterables::firstKey(new ArrayIterator(['a' => 1, 'b' => 2])); // 'a'
Iterables::firstKey(new ArrayIterator([])); // null
map (iterable $iterable, callable $transformer): Generator
Creates a new iterator by applying the $transformer
callback to each element of the original iterator. The
callback $transformer
has the signature function ($value, $key, iterable $iterable): mixed
, and its
return value is used as the new value of the element.
$iterator = new ArrayIterator([1, 2, 3]);
$iterator = Iterables::map($iterator, fn($v) => $v * 2);
// 2, 4, 6
The method uses a generator, meaning the transformation occurs incrementally as you iterate through the result. This is memory-efficient and allows processing very large collections. If you don't iterate through all elements of the resulting iterator, you save computational power because not all elements of the original iterator are processed.
mapWithKeys (iterable $iterable, callable $transformer): Generator
Creates a new iterator by transforming the values and keys of the original iterator. The callback $transformer
has
the signature function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}
. If $transformer
returns null
, the element is skipped. For retained elements, the first element of the returned array is used as the
new key, and the second element as the new value.
$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
// [4 => 'B']
Like map()
, this method uses a generator for incremental processing and memory efficiency. This allows working
with large collections and saving computational power when only partially iterating through the result.
memoize (iterable $iterable): IteratorAggregate
Creates a wrapper around an iterator that caches its keys and values during iteration. This allows repeated iteration over the data without needing to traverse the original data source again.
$iterator = /* data that cannot be iterated multiple times */;
$memoized = Iterables::memoize($iterator);
// Now you can iterate $memoized multiple times without data loss
This method is useful in situations where you need to iterate over the same dataset multiple times, but the original iterator doesn't allow repeated iteration, or re-traversing would be costly (e.g., reading data from a database or file).
some (iterable $iterable, callable $predicate): bool
Checks if at least one element of the iterator satisfies the condition defined in $predicate
. The callback
$predicate
has the signature function ($value, $key, iterable $iterable): bool
and must return
true
for at least one element for the some()
method to return true
.
$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
$isEven = fn($value) => $value % 2 === 0;
$res = Iterables::some($iterator, $isEven); // true
This method is useful for quickly verifying if at least one element in a collection meets a certain condition, for example, whether the collection contains at least one even number.
See every().
toIterator (iterable $iterable): Iterator
Converts any iterable object (array, Traversable) into an Iterator. If the input is already an Iterator, it is returned unchanged.
$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Now you have an Iterator instead of an array
This method is useful when you need to ensure you have an Iterator available, regardless of the input data type. This can be helpful when creating functions that work with various types of iterable data.