Trabajando con iteradores

Nette\Utils\Iterables es una clase estática con funciones para trabajar con iteradores. Su contraparte para arrays es Nette\Utils\Arrays.

Instalación:

composer require nette/utils

Todos los ejemplos asumen que se ha creado un alias:

use Nette\Utils\Iterables;

contains (iterable $iterable, $value)bool

Busca un valor específico en el iterador. Utiliza una comparación estricta (===) para verificar la coincidencia. Devuelve true si se encuentra el valor, de lo contrario false.

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

Este método es útil cuando necesita determinar rápidamente si un valor particular está presente en el iterador sin tener que recorrer manualmente todos los elementos.

containsKey (iterable $iterable, $key)bool

Busca una clave específica en el iterador. Utiliza una comparación estricta (===) para verificar la coincidencia. Devuelve true si se encuentra la clave, de lo contrario 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 si todos los elementos del iterador cumplen la condición definida en $predicate. La función $predicate tiene la firma function ($value, $key, iterable $iterable): bool y debe devolver true para cada elemento para que el método every() devuelva true.

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

Este método es útil para verificar si todos los elementos de una colección cumplen una determinada condición, por ejemplo, si todos los números son menores que un valor determinado.

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

Crea un nuevo iterador que contiene solo aquellos elementos del iterador original que cumplen la condición definida en $predicate. La función $predicate tiene la firma function ($value, $key, iterable $iterable): bool y debe devolver true para los elementos que se deben conservar.

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

El método utiliza un generador, lo que significa que el filtrado se realiza gradualmente al recorrer el resultado. Esto es eficiente en términos de memoria y permite procesar colecciones muy grandes. Si no recorre todos los elementos del iterador resultante, ahorrará potencia de cálculo, ya que no se procesarán todos los elementos del iterador original.

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

Devuelve el primer elemento del iterador. Si se especifica $predicate, devuelve el primer elemento que cumple la condición dada. La función $predicate tiene la firma function ($value, $key, iterable $iterable): bool. Si no se encuentra ningún elemento que coincida, se llama a la función $else (si se especifica) y se devuelve su resultado. Si no se especifica $else, se devuelve 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 es útil cuando necesita obtener rápidamente el primer elemento de una colección o el primer elemento que cumple una determinada condición, sin tener que recorrer manualmente toda la colección.

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

Devuelve la clave del primer elemento del iterador. Si se especifica $predicate, devuelve la clave del primer elemento que cumple la condición dada. La función $predicate tiene la firma function ($value, $key, iterable $iterable): bool. Si no se encuentra ningún elemento que coincida, se llama a la función $else (si se especifica) y se devuelve su resultado. Si no se especifica $else, se devuelve 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

Crea un nuevo iterador aplicando la función $transformer a cada elemento del iterador original. La función $transformer tiene la firma function ($value, $key, iterable $iterable): mixed y su valor de retorno se utiliza como el nuevo valor del elemento.

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

El método utiliza un generador, lo que significa que la transformación se realiza gradualmente al recorrer el resultado. Esto es eficiente en términos de memoria y permite procesar colecciones muy grandes. Si no recorre todos los elementos del iterador resultante, ahorrará potencia de cálculo, ya que no se procesarán todos los elementos del iterador original.

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

Crea un nuevo iterador transformando los valores y claves del iterador original. La función $transformer tiene la firma function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}. Si $transformer devuelve null, el elemento se omite. Para los elementos conservados, el primer elemento del array devuelto se utiliza como la nueva clave y el segundo elemento como el nuevo valor.

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

Al igual que map(), este método utiliza un generador para el procesamiento gradual y el trabajo eficiente con la memoria. Esto permite trabajar con colecciones grandes y ahorrar potencia de cálculo en el recorrido parcial del resultado.

memoize (iterable $iterable): IteratorAggregate

Crea un envoltorio alrededor de un iterador que almacena en caché sus claves y valores durante la iteración. Esto permite la iteración repetida de datos sin necesidad de volver a recorrer la fuente de datos original.

$iterator = /* datos que no se pueden iterar más de una vez */
$memoized = Iterables::memoize($iterator);
// Ahora puedes iterar $memoized varias veces sin perder datos

Este método es útil en situaciones en las que necesita recorrer el mismo conjunto de datos varias veces, pero el iterador original no permite la iteración repetida o el recorrido repetido sería costoso (por ejemplo, al leer datos de una base de datos o un archivo).

some (iterable $iterable, callable $predicate)bool

Verifica si al menos un elemento del iterador cumple la condición definida en $predicate. La función $predicate tiene la firma function ($value, $key, iterable $iterable): bool y debe devolver true para al menos un elemento para que el método some() devuelva 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 es útil para verificar rápidamente si existe al menos un elemento en la colección que cumpla una determinada condición, por ejemplo, si la colección contiene al menos un número par.

Ver every().

toIterator (iterable $iterable): Iterator

Convierte cualquier objeto iterable (array, Traversable) en un Iterator. Si la entrada ya es un Iterator, lo devuelve sin cambios.

$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Ahora tienes un Iterator en lugar de un array

Este método es útil cuando necesita asegurarse de que tiene un Iterator disponible, independientemente del tipo de datos de entrada. Esto puede ser útil al crear funciones que trabajan con diferentes tipos de datos iterables.

versión: 4.0