Робота з ітераторами
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, незалежно від типу вхідних даних. Це може бути корисним при створенні функцій, які працюють з різними типами ітерованих даних.