Praca z iteratorami

Nette\Utils\Iterables to klasa statyczna z funkcjami do pracy z iteratorami. Jej odpowiednikiem dla tablic jest Nette\Utils\Arrays.

Instalacja:

composer require nette/utils

Wszystkie przykłady zakładają utworzony alias:

use Nette\Utils\Iterables;

contains (iterable $iterable, $value)bool

Szuka podanej wartości w iteratorze. Używa ścisłego porównania (===) do sprawdzenia zgodności. Zwraca true, jeśli wartość zostanie znaleziona, w przeciwnym razie false.

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

Ta metoda jest przydatna, gdy potrzebujesz szybko sprawdzić, czy określona wartość znajduje się w iteratorze, bez konieczności ręcznego przeglądania wszystkich elementów.

containsKey (iterable $iterable, $key)bool

Szuka podanego klucza w iteratorze. Używa ścisłego porównania (===) do sprawdzenia zgodności. Zwraca true, jeśli klucz zostanie znaleziony, w przeciwnym razie 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

Sprawdza, czy wszystkie elementy iteratora spełniają warunek zdefiniowany w $predicate. Funkcja $predicate ma sygnaturę function ($value, $key, iterable $iterable): bool i musi zwracać true dla każdego elementu, aby metoda every() zwróciła true.

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

Ta metoda jest przydatna do sprawdzenia, czy wszystkie elementy w kolekcji spełniają określony warunek, na przykład czy wszystkie liczby są mniejsze od określonej wartości.

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

Tworzy nowy iterator, który zawiera tylko te elementy z oryginalnego iteratora, które spełniają warunek zdefiniowany w $predicate. Funkcja $predicate ma sygnaturę function ($value, $key, iterable $iterable): bool i musi zwracać true dla elementów, które mają być zachowane.

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

Metoda wykorzystuje generator, co oznacza, że filtrowanie odbywa się stopniowo podczas przeglądania wyniku. Jest to efektywne pod względem pamięci i pozwala przetwarzać nawet bardzo duże kolekcje. Jeśli nie przejdziesz wszystkich elementów wynikowego iteratora, oszczędzisz moc obliczeniową, ponieważ nie przetworzą się wszystkie elementy oryginalnego iteratora.

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

Zwraca pierwszy element iteratora. Jeśli podano $predicate, zwraca pierwszy element, który spełnia podany warunek. Funkcja $predicate ma sygnaturę function ($value, $key, iterable $iterable): bool. Jeśli nie znaleziono żadnego pasującego elementu, wywoływana jest funkcja $else (jeśli jest podana) i zwracany jest jej wynik. Jeśli $else nie jest podane, zwracane jest 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

Ta metoda jest przydatna, gdy potrzebujesz szybko uzyskać pierwszy element kolekcji lub pierwszy element spełniający określony warunek, bez konieczności ręcznego przeglądania całej kolekcji.

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

Zwraca klucz pierwszego elementu iteratora. Jeśli podano $predicate, zwraca klucz pierwszego elementu, który spełnia podany warunek. Funkcja $predicate ma sygnaturę function ($value, $key, iterable $iterable): bool. Jeśli nie znaleziono żadnego pasującego elementu, wywoływana jest funkcja $else (jeśli jest podana) i zwracany jest jej wynik. Jeśli $else nie jest podane, zwracane jest 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

Tworzy nowy iterator, stosując funkcję $transformer do każdego elementu oryginalnego iteratora. Funkcja $transformer ma sygnaturę function ($value, $key, iterable $iterable): mixed i jej wartość zwracana jest używana jako nowa wartość elementu.

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

Metoda wykorzystuje generator, co oznacza, że transformacja odbywa się stopniowo podczas przeglądania wyniku. Jest to efektywne pod względem pamięci i pozwala przetwarzać nawet bardzo duże kolekcje. Jeśli nie przejdziesz wszystkich elementów wynikowego iteratora, oszczędzisz moc obliczeniową, ponieważ nie przetworzą się wszystkie elementy oryginalnego iteratora.

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

Tworzy nowy iterator, transformując wartości i klucze oryginalnego iteratora. Funkcja $transformer ma sygnaturę function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}. Jeśli $transformer zwróci null, element jest pomijany. Dla zachowanych elementów pierwszy element zwróconej tablicy jest używany jako nowy klucz, a drugi element jako nowa wartość.

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

Podobnie jak map(), ta metoda wykorzystuje generator do stopniowego przetwarzania i efektywnej pracy z pamięcią. Pozwala to pracować z dużymi kolekcjami i oszczędzać moc obliczeniową przy częściowym przejściu przez wynik.

memoize (iterable $iterable): IteratorAggregate

Tworzy opakowanie wokół iteratora, które podczas iteracji zapisuje w pamięci podręcznej jego klucze i wartości. Pozwala to na wielokrotną iterację danych bez konieczności ponownego przechodzenia przez oryginalne źródło danych.

$iterator = /* dane, których nie można iterować wielokrotnie */
$memoized = Iterables::memoize($iterator);
// Teraz możesz iterować $memoized wielokrotnie bez utraty danych

Ta metoda jest przydatna w sytuacjach, gdy potrzebujesz wielokrotnie przejść przez ten sam zestaw danych, ale oryginalny iterator nie pozwala na wielokrotną iterację lub ponowne przejście byłoby kosztowne (np. przy odczycie danych z bazy danych lub pliku).

some (iterable $iterable, callable $predicate)bool

Sprawdza, czy przynajmniej jeden element iteratora spełnia warunek zdefiniowany w $predicate. Funkcja $predicate ma sygnaturę function ($value, $key, iterable $iterable): bool i musi zwracać true dla przynajmniej jednego elementu, aby metoda some() zwróciła true.

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

Ta metoda jest przydatna do szybkiego sprawdzenia, czy w kolekcji istnieje przynajmniej jeden element spełniający określony warunek, na przykład czy kolekcja zawiera przynajmniej jedną liczbę parzystą.

Zobacz every().

toIterator (iterable $iterable): Iterator

Konwertuje dowolny obiekt iterowalny (array, Traversable) na Iterator. Jeśli wejście jest już Iteratorem, zwraca go bez zmian.

$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Teraz masz Iterator zamiast tablicy

Ta metoda jest przydatna, gdy potrzebujesz zapewnić, że masz do dyspozycji Iterator, niezależnie od typu danych wejściowych. Może to być przydatne przy tworzeniu funkcji, które pracują z różnymi typami danych iterowalnych.

wersja: 4.0