Функции на итератора
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, независимо от типа на входните данни. Това може да бъде полезно при създаване на функции, които работят с различни типове итерационни данни.