Функции на итератора

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 = /* data that cannot be iterated multiple times */
$memoized = Iterables::memoize($iterator);
// Now you can iterate $memoized multiple times without data loss

Този метод е полезен в ситуации, в които е необходимо да се итерира многократно един и същ набор от данни, но оригиналният итератор не поддържа многократна итерация или многократната итерация би била скъпа (например четене на данни от база данни или файл).

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

Преобразува всеки обект с итерации (масив, Traversable) в итератор. Ако входният обект вече е Iterator, той се връща непроменен.

$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Now you have an Iterator instead of an array

Този метод е полезен, когато трябва да се уверите, че имате Iterator, независимо от типа на входните данни. Това може да бъде полезно при създаване на функции, които работят с различни типове итерационни данни.

версия: 4.0