Trabalhando com iteradores

Nette\Utils\Iterables é uma classe estática com funções para trabalhar com iteradores. Seu equivalente para arrays é Nette\Utils\Arrays.

Instalação:

composer require nette/utils

Todos os exemplos assumem que um alias foi criado:

use Nette\Utils\Iterables;

contains (iterable $iterable, $value)bool

Procura o valor especificado no iterador. Usa comparação estrita (===) para verificar a correspondência. Retorna true se o valor for encontrado, caso contrário false.

Iterables::contains(new ArrayIterator([1, 2, 3]), 1);    // true
Iterables::contains(new ArrayIterator([1, 2, 3]), '1');  // false

Este método é útil quando você precisa descobrir rapidamente se um valor específico está no iterador sem ter que percorrer todos os elementos manualmente.

containsKey (iterable $iterable, $key)bool

Procura a chave especificada no iterador. Usa comparação estrita (===) para verificar a correspondência. Retorna true se a chave for encontrada, caso contrário 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

Verifica se todos os elementos do iterador satisfazem a condição definida em $predicate. A função $predicate tem a assinatura function ($value, $key, iterable $iterable): bool e deve retornar true para cada elemento para que o método every() retorne true.

$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
$isBelowThreshold = fn($value) => $value < 40;
$res = Iterables::every($iterator, $isBelowThreshold); // true

Este método é útil para verificar se todos os elementos em uma coleção satisfazem uma determinada condição, por exemplo, se todos os números são menores que um determinado valor.

filter (iterable $iterable, callable $predicate): Generator

Cria um novo iterador que contém apenas os elementos do iterador original que satisfazem a condição definida em $predicate. A função $predicate tem a assinatura function ($value, $key, iterable $iterable): bool e deve retornar true para os elementos que devem ser mantidos.

$iterator = new ArrayIterator([1, 2, 3]);
$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
// 1, 2

O método utiliza um gerador, o que significa que a filtragem ocorre gradualmente ao percorrer o resultado. Isso é eficiente em termos de memória e permite processar coleções muito grandes. Se você não percorrer todos os elementos do iterador resultante, economizará poder de processamento, pois nem todos os elementos do iterador original serão processados.

first (iterable $iterable, ?callable $predicate=null, ?callable $else=null)mixed

Retorna o primeiro elemento do iterador. Se $predicate for especificado, retorna o primeiro elemento que satisfaz a condição dada. A função $predicate tem a assinatura function ($value, $key, iterable $iterable): bool. Se nenhum elemento correspondente for encontrado, a função $else é chamada (se especificada) e seu resultado é retornado. Se $else não for especificado, retorna null.

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

Este método é útil quando você precisa obter rapidamente o primeiro elemento de uma coleção ou o primeiro elemento que satisfaz uma determinada condição, sem ter que percorrer toda a coleção manualmente.

firstKey (iterable $iterable, ?callable $predicate=null, ?callable $else=null)mixed

Retorna a chave do primeiro elemento do iterador. Se $predicate for especificado, retorna a chave do primeiro elemento que satisfaz a condição dada. A função $predicate tem a assinatura function ($value, $key, iterable $iterable): bool. Se nenhum elemento correspondente for encontrado, a função $else é chamada (se especificada) e seu resultado é retornado. Se $else não for especificado, retorna null.

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

Cria um novo iterador aplicando a função $transformer a cada elemento do iterador original. A função $transformer tem a assinatura function ($value, $key, iterable $iterable): mixed e seu valor de retorno é usado como o novo valor do elemento.

$iterator = new ArrayIterator([1, 2, 3]);
$iterator = Iterables::map($iterator, fn($v) => $v * 2);
// 2, 4, 6

O método utiliza um gerador, o que significa que a transformação ocorre gradualmente ao percorrer o resultado. Isso é eficiente em termos de memória e permite processar coleções muito grandes. Se você não percorrer todos os elementos do iterador resultante, economizará poder de processamento, pois nem todos os elementos do iterador original serão processados.

mapWithKeys (iterable $iterable, callable $transformer): Generator

Cria um novo iterador transformando os valores e chaves do iterador original. A função $transformer tem a assinatura function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}. Se $transformer retornar null, o elemento é ignorado. Para os elementos mantidos, o primeiro elemento do array retornado é usado como a nova chave e o segundo elemento como o novo valor.

$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
// [4 => 'B']

Assim como map(), este método utiliza um gerador para processamento gradual e trabalho eficiente com a memória. Isso permite trabalhar com grandes coleções e economizar poder de processamento ao percorrer parcialmente o resultado.

memoize (iterable $iterable): IteratorAggregate

Cria um invólucro em torno do iterador que armazena em cache suas chaves e valores durante a iteração. Isso permite a iteração repetida dos dados sem a necessidade de percorrer novamente a fonte de dados original.

$iterator = /* dados que não podem ser iterados mais de uma vez */
$memoized = Iterables::memoize($iterator);
// Agora você pode iterar $memoized várias vezes sem perder dados

Este método é útil em situações em que você precisa percorrer o mesmo conjunto de dados várias vezes, mas o iterador original não permite iteração repetida ou a passagem repetida seria cara (por exemplo, ao ler dados de um banco de dados ou arquivo).

some (iterable $iterable, callable $predicate)bool

Verifica se pelo menos um elemento do iterador satisfaz a condição definida em $predicate. A função $predicate tem a assinatura function ($value, $key, iterable $iterable): bool e deve retornar true para pelo menos um elemento para que o método some() retorne true.

$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
$isEven = fn($value) => $value % 2 === 0;
$res = Iterables::some($iterator, $isEven); // true

Este método é útil para verificar rapidamente se existe pelo menos um elemento na coleção que satisfaz uma determinada condição, por exemplo, se a coleção contém pelo menos um número par.

Veja every().

toIterator (iterable $iterable): Iterator

Converte qualquer objeto iterável (array, Traversable) em um Iterator. Se a entrada já for um Iterator, retorna-o sem alterações.

$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Agora você tem um Iterator em vez de um array

Este método é útil quando você precisa garantir que tem um Iterator disponível, independentemente do tipo de dados de entrada. Isso pode ser útil ao criar funções que trabalham com diferentes tipos de dados iteráveis.

versão: 4.0