Arbeiten mit Iteratoren

Nette\Utils\Iterables ist eine statische Klasse mit Funktionen für die Arbeit mit Iteratoren. Ihr Gegenstück für Arrays ist Nette\Utils\Arrays.

Installation:

composer require nette/utils

Alle Beispiele setzen voraus, dass dieser Alias angelegt wurde:

use Nette\Utils\Iterables;

contains (iterable $iterable, $value)bool

Sucht einen angegebenen Wert in einem Iterator. Für die Prüfung auf Übereinstimmung wird ein strikter Vergleich (===) verwendet. Gibt true zurück, wenn der Wert gefunden wird, sonst false.

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

Diese Methode ist nützlich, wenn Sie schnell feststellen müssen, ob ein bestimmter Wert in einem Iterator vorkommt, ohne alle Elemente von Hand zu durchlaufen.

containsKey (iterable $iterable, $key)bool

Sucht einen angegebenen Schlüssel in einem Iterator. Für die Prüfung auf Übereinstimmung wird ein strikter Vergleich (===) verwendet. Gibt true zurück, wenn der Schlüssel gefunden wird, sonst 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

Prüft, ob alle Elemente des Iterators die in $predicate definierte Bedingung erfüllen. Der Callback $predicate hat die Signatur function ($value, $key, iterable $iterable): bool und muss für jedes Element true zurückgeben, damit die Methode every() true zurückgibt.

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

Diese Methode ist nützlich, um zu prüfen, ob alle Elemente einer Sammlung eine bestimmte Bedingung erfüllen, etwa ob alle Zahlen kleiner als ein bestimmter Wert sind.

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

Erzeugt einen neuen Iterator, der nur die Elemente des ursprünglichen Iterators enthält, die die in $predicate definierte Bedingung erfüllen. Der Callback $predicate hat die Signatur function ($value, $key, iterable $iterable): bool und muss für die Elemente true zurückgeben, die erhalten bleiben sollen.

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

Die Methode verwendet einen Generator, das Filtern geschieht also nach und nach, während Sie das Ergebnis durchlaufen. Das ist speicherschonend und erlaubt die Verarbeitung sehr großer Sammlungen. Wenn Sie nicht alle Elemente des resultierenden Iterators durchlaufen, sparen Sie Rechenleistung, weil nicht alle Elemente des ursprünglichen Iterators verarbeitet werden.

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

Gibt das erste Element des Iterators zurück. Ist $predicate angegeben, gibt sie das erste Element zurück, das die Bedingung erfüllt. Der Callback $predicate hat die Signatur function ($value, $key, iterable $iterable): bool. Wird kein passendes Element gefunden, wird der Callback $else aufgerufen (sofern angegeben) und sein Ergebnis zurückgegeben. Ist $else nicht angegeben, wird null zurückgegeben.

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

Diese Methode ist nützlich, wenn Sie schnell das erste Element einer Sammlung oder das erste Element mit einer bestimmten Eigenschaft brauchen, ohne die gesamte Sammlung von Hand zu durchlaufen.

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

Gibt den Schlüssel des ersten Elements des Iterators zurück. Ist $predicate angegeben, gibt sie den Schlüssel des ersten Elements zurück, das die Bedingung erfüllt. Der Callback $predicate hat die Signatur function ($value, $key, iterable $iterable): bool. Wird kein passendes Element gefunden, wird der Callback $else aufgerufen (sofern angegeben) und sein Ergebnis zurückgegeben. Ist $else nicht angegeben, wird null zurückgegeben.

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

Erzeugt einen neuen Iterator, indem der Callback $transformer auf jedes Element des ursprünglichen Iterators angewendet wird. Der Callback $transformer hat die Signatur function ($value, $key, iterable $iterable): mixed, und sein Rückgabewert dient als neuer Wert des Elements.

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

Die Methode verwendet einen Generator, die Transformation geschieht also nach und nach, während Sie das Ergebnis durchlaufen. Das ist speicherschonend und erlaubt die Verarbeitung sehr großer Sammlungen. Wenn Sie nicht alle Elemente des resultierenden Iterators durchlaufen, sparen Sie Rechenleistung, weil nicht alle Elemente des ursprünglichen Iterators verarbeitet werden.

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

Erzeugt einen neuen Iterator, indem die Werte und Schlüssel des ursprünglichen Iterators transformiert werden. Der Callback $transformer hat die Signatur function ($value, $key, iterable $iterable): ?array{$newKey, $newValue}. Gibt $transformer den Wert null zurück, wird das Element übersprungen. Bei den behaltenen Elementen dient das erste Element des zurückgegebenen Arrays als neuer Schlüssel und das zweite als neuer Wert.

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

Wie map() verwendet auch diese Methode einen Generator, verarbeitet also nach und nach und schont den Speicher. So lässt sich mit großen Sammlungen arbeiten und Rechenleistung sparen, wenn Sie das Ergebnis nur teilweise durchlaufen.

memoize (iterable $iterable): IteratorAggregate

Erzeugt einen Wrapper um einen Iterator, der dessen Schlüssel und Werte während des Durchlaufs zwischenspeichert. Das erlaubt es, die Daten mehrfach zu durchlaufen, ohne die ursprüngliche Datenquelle erneut zu durchlaufen.

$iterator = /* ... */; // Daten, die sich nicht mehrfach durchlaufen lassen
$memoized = Iterables::memoize($iterator);
// Jetzt lässt sich $memoized mehrfach durchlaufen, ohne Daten zu verlieren

Diese Methode ist in Situationen nützlich, in denen Sie dieselbe Datenmenge mehrfach durchlaufen müssen, der ursprüngliche Iterator aber kein wiederholtes Durchlaufen erlaubt oder ein erneuter Durchlauf teuer wäre (etwa beim Lesen von Daten aus einer Datenbank oder Datei).

repeatable (callable $factory): IteratorAggregate

Erlaubt das wiederholte Durchlaufen von Objekten, die das sonst nicht unterstützen, typischerweise von PHP-Generatoren. Die Methode repeatable() löst dieses Problem elegant: Statt des Iterators selbst übergeben Sie eine Funktion, die ihn erzeugt. Diese Factory wird dann bei jedem Durchlauf automatisch aufgerufen.

// Ein üblicher Generator, der sich nicht zweimal durchlaufen lässt
$generator = function () {
	yield 'A';
	yield 'B';
};

$iterator = Iterables::repeatable($generator);

foreach ($iterator as $v) echo $v; // Gibt aus: AB
foreach ($iterator as $v) echo $v; // Gibt aus: AB (der Generator lief erneut)

Diese Methode ist eine Alternative zu memoize() in Situationen, in denen Sie mit großen Datenmengen arbeiten, denn repeatable() speichert die Daten nicht zwischen, sondern erzeugt sie bei jedem Durchlauf neu.

some (iterable $iterable, callable $predicate)bool

Prüft, ob mindestens ein Element des Iterators die in $predicate definierte Bedingung erfüllt. Der Callback $predicate hat die Signatur function ($value, $key, iterable $iterable): bool und muss für mindestens ein Element true zurückgeben, damit die Methode some() true zurückgibt.

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

Diese Methode ist nützlich, um schnell zu prüfen, ob mindestens ein Element einer Sammlung eine bestimmte Bedingung erfüllt, etwa ob die Sammlung mindestens eine gerade Zahl enthält.

Siehe every().

toIterator (iterable $iterable): Iterator

Wandelt ein beliebiges iterierbares Objekt (Array, Traversable) in einen Iterator um. Ist die Eingabe bereits ein Iterator, wird sie unverändert zurückgegeben.

$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Jetzt haben Sie statt eines Arrays einen Iterator

Diese Methode ist nützlich, wenn Sie sicherstellen müssen, dass Ihnen ein Iterator zur Verfügung steht, unabhängig vom Typ der Eingabedaten. Das kann beim Schreiben von Funktionen helfen, die mit verschiedenen Arten iterierbarer Daten arbeiten.

Version: 4.x