Робота з ітераторами

Nette\Utils\Iterables — це статичний клас з функціями для роботи з ітераторами. Його аналогом для масивів є Nette\Utils\Arrays.

Встановлення:

composer require nette/utils

Усі приклади передбачають створений псевдонім:

use Nette\Utils\Iterables;

contains (iterable $iterable, $value)bool

Шукає задане значення в ітераторі. Використовує строге порівняння (===) для перевірки збігу. Повертає true, якщо значення знайдено, інакше false.

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

Цей метод корисний, коли потрібно швидко дізнатися, чи знаходиться конкретне значення в ітераторі, не перебираючи всі елементи вручну.

containsKey (iterable $iterable, $key)bool

Шукає заданий ключ в ітераторі. Використовує строге порівняння (===) для перевірки збігу. Повертає true, якщо ключ знайдено, інакше 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

Перевіряє, чи всі елементи ітератора задовольняють умову, визначену в $predicate. Функція $predicate має сигнатуру function ($value, $key, iterable $iterable): bool і повинна повертати true для кожного елемента, щоб метод every() повернув true.

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

Цей метод корисний для перевірки, чи всі елементи в колекції задовольняють певну умову, наприклад, чи всі числа менші за певне значення.

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

Створює новий ітератор, який містить лише ті елементи з вихідного ітератора, які задовольняють умову, визначену в $predicate. Функція $predicate має сигнатуру function ($value, $key, iterable $iterable): bool і повинна повертати true для елементів, які мають бути збережені.

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

Метод використовує генератор, що означає, що фільтрація відбувається поступово під час перебору результату. Це ефективно з точки зору пам'яті та дозволяє обробляти навіть дуже великі колекції. Якщо ви не пройдете всі елементи результуючого ітератора, ви заощадите обчислювальну потужність, оскільки не всі елементи вихідного ітератора будуть оброблені.

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

Повертає перший елемент ітератора. Якщо задано $predicate, повертає перший елемент, який задовольняє задану умову. Функція $predicate має сигнатуру function ($value, $key, iterable $iterable): bool. Якщо не знайдено жодного відповідного елемента, викликається функція $else (якщо вона задана) і повертається її результат. Якщо $else не задано, повертається 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

Цей метод корисний, коли потрібно швидко отримати перший елемент колекції або перший елемент, що задовольняє певну умову, не перебираючи всю колекцію вручну.

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

Повертає ключ першого елемента ітератора. Якщо задано $predicate, повертає ключ першого елемента, який задовольняє задану умову. Функція $predicate має сигнатуру function ($value, $key, iterable $iterable): bool. Якщо не знайдено жодного відповідного елемента, викликається функція $else (якщо вона задана) і повертається її результат. Якщо $else не задано, повертається 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

Створює новий ітератор, застосовуючи функцію $transformer до кожного елемента вихідного ітератора. Функція $transformer має сигнатуру function ($value, $key, iterable $iterable): mixed, і її повернене значення використовується як нове значення елемента.

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

Метод використовує генератор, що означає, що трансформація відбувається поступово під час перебору результату. Це ефективно з точки зору пам'яті та дозволяє обробляти навіть дуже великі колекції. Якщо ви не пройдете всі елементи результуючого ітератора, ви заощадите обчислювальну потужність, оскільки не всі елементи вихідного ітератора будуть оброблені.

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

Створює новий ітератор, трансформуючи значення та ключі вихідного ітератора. Функція $transformer має сигнатуру function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}. Якщо $transformer повертає null, елемент пропускається. Для збережених елементів перший елемент повернутого масиву використовується як новий ключ, а другий елемент — як нове значення.

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

Так само, як map(), цей метод використовує генератор для поступової обробки та ефективної роботи з пам'яттю. Це дозволяє працювати з великими колекціями та економити обчислювальну потужність при частковому переборі результату.

memoize (iterable $iterable): IteratorAggregate

Створює обгортку навколо ітератора, яка під час ітерації кешує його ключі та значення. Це дозволяє повторно ітерувати дані без необхідності знову проходити вихідне джерело даних.

$iterator = /* дані, які не можна ітерувати більше одного разу */
$memoized = Iterables::memoize($iterator);
// Тепер ви можете ітерувати $memoized кілька разів без втрати даних

Цей метод корисний у ситуаціях, коли потрібно кілька разів пройти один і той же набір даних, але вихідний ітератор не дозволяє повторної ітерації або повторний перебір був би витратним (наприклад, при читанні даних з бази даних або файлу).

some (iterable $iterable, callable $predicate)bool

Перевіряє, чи хоча б один елемент ітератора задовольняє умову, визначену в $predicate. Функція $predicate має сигнатуру function ($value, $key, iterable $iterable): bool і повинна повертати true для хоча б одного елемента, щоб метод some() повернув true.

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

Цей метод корисний для швидкої перевірки, чи існує в колекції хоча б один елемент, що задовольняє певну умову, наприклад, чи містить колекція хоча б одне парне число.

Див. every().

toIterator (iterable $iterable): Iterator

Перетворює будь-який ітерований об'єкт (array, Traversable) на Iterator. Якщо вхідні дані вже є Iterator, повертає його без змін.

$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Тепер у вас є Iterator замість масиву

Цей метод корисний, коли потрібно забезпечити наявність Iterator, незалежно від типу вхідних даних. Це може бути корисним при створенні функцій, які працюють з різними типами ітерованих даних.

версія: 4.0