Iterator'larla Çalışma
Nette\Utils\Iterables, iterator'larla çalışmaya yarayan fonksiyonlar içeren statik bir sınıftır. Diziler için karşılığı Nette\Utils\Arrays sınıfıdır.
Kurulum:
composer require nette/utils
Tüm örnekler, aşağıdaki takma adın oluşturulduğunu varsayar:
use Nette\Utils\Iterables;
contains (iterable $iterable, $value): bool
Bir iterator içinde verilen değeri arar. Eşleşmeyi denetlerken katı karşılaştırma (===) kullanır. Değer
bulunursa true, aksi hâlde false döndürür.
Iterables::contains(new ArrayIterator([1, 2, 3]), 1); // true
Iterables::contains(new ArrayIterator([1, 2, 3]), '1'); // false
Bu metot, tüm öğeleri elle dolaşmadan belirli bir değerin iterator'da bulunup bulunmadığını hızlıca belirlemeniz gerektiğinde işe yarar.
containsKey (iterable $iterable, $key): bool
Bir iterator içinde verilen anahtarı arar. Eşleşmeyi denetlerken katı karşılaştırma (===) kullanır.
Anahtar bulunursa true, aksi hâlde false döndürür.
Iterables::containsKey(new ArrayIterator([1, 2, 3]), 0); // true
Iterables::containsKey(new ArrayIterator([1, 2, 3]), 4); // false
every (iterable $iterable, callable $predicate): bool
Iterator'ın tüm öğelerinin $predicate ile tanımlanan koşulu sağlayıp sağlamadığını denetler.
$predicate callback'inin imzası function ($value, $key, iterable $iterable): bool şeklindedir ve
every() metodunun true döndürmesi için her öğede true döndürmelidir.
$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
$isBelowThreshold = fn($value) => $value < 40;
$res = Iterables::every($iterator, $isBelowThreshold); // true
Bu metot, bir koleksiyondaki tüm öğelerin belirli bir koşulu karşıladığını doğrulamak için kullanışlıdır; örneğin tüm sayıların belirli bir değerden küçük olup olmadığını.
filter (iterable $iterable, callable $predicate): Generator
Özgün iterator'dan yalnızca $predicate ile tanımlanan koşulu sağlayan öğeleri içeren yeni bir iterator
oluşturur. $predicate callback'inin imzası function ($value, $key, iterable $iterable): bool
şeklindedir ve korunması gereken öğeler için true döndürmelidir.
$iterator = new ArrayIterator([1, 2, 3]);
$iterator = Iterables::filter($iterator, fn($v) => $v < 3);
// 1, 2
Metot bir generator kullanır; yani filtreleme, sonucu dolaştıkça adım adım gerçekleşir. Bu bellek açısından verimlidir ve çok büyük koleksiyonların işlenmesine olanak tanır. Ortaya çıkan iterator'ın tüm öğelerini dolaşmazsanız, özgün iterator'ın tüm öğeleri işlenmediği için hesaplama gücünden tasarruf edersiniz.
first (iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed
Iterator'ın ilk öğesini döndürür. $predicate verilmişse, koşulu sağlayan ilk öğeyi döndürür.
$predicate callback'inin imzası function ($value, $key, iterable $iterable): bool şeklindedir. Uyan
bir öğe bulunmazsa (verilmişse) $else callback'i çağrılır ve sonucu döndürülür. $else
verilmemişse null döndürülür.
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
Bu metot, koleksiyonun tamamını elle dolaşmadan ilk öğesini ya da belirli bir koşulu sağlayan ilk öğesini hızlıca almanız gerektiğinde işe yarar.
firstKey (iterable $iterable, ?callable $predicate=null, ?callable $else=null): mixed
Iterator'ın ilk öğesinin anahtarını döndürür. $predicate verilmişse, koşulu sağlayan ilk öğenin
anahtarını döndürür. $predicate callback'inin imzası
function ($value, $key, iterable $iterable): bool şeklindedir. Uyan bir öğe bulunmazsa (verilmişse)
$else callback'i çağrılır ve sonucu döndürülür. $else verilmemişse null
döndürülür.
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
Özgün iterator'ın her öğesine $transformer callback'ini uygulayarak yeni bir iterator oluşturur.
$transformer callback'inin imzası function ($value, $key, iterable $iterable): mixed şeklindedir ve
döndürdüğü değer öğenin yeni değeri olarak kullanılır.
$iterator = new ArrayIterator([1, 2, 3]);
$iterator = Iterables::map($iterator, fn($v) => $v * 2);
// 2, 4, 6
Metot bir generator kullanır; yani dönüşüm, sonucu dolaştıkça adım adım gerçekleşir. Bu bellek açısından verimlidir ve çok büyük koleksiyonların işlenmesine olanak tanır. Ortaya çıkan iterator'ın tüm öğelerini dolaşmazsanız, özgün iterator'ın tüm öğeleri işlenmediği için hesaplama gücünden tasarruf edersiniz.
mapWithKeys (iterable $iterable, callable $transformer): Generator
Özgün iterator'ın değerlerini ve anahtarlarını dönüştürerek yeni bir iterator oluşturur. $transformer
callback'inin imzası function ($value, $key, iterable $iterable): ?array{$newKey, $newValue} şeklindedir.
$transformer null döndürürse öğe atlanır. Korunan öğelerde, döndürülen dizinin ilk öğesi
yeni anahtar, ikinci öğesi yeni değer olarak kullanılır.
$iterator = new ArrayIterator(['a' => 1, 'b' => 2]);
$iterator = Iterables::mapWithKeys($iterator, fn($v, $k) => $v > 1 ? [$v * 2, strtoupper($k)] : null);
// [4 => 'B']
map() gibi bu metot da adım adım işleme ve bellek verimliliği için bir generator kullanır. Böylece büyük
koleksiyonlarla çalışabilir ve sonucu yalnızca kısmen dolaştığınızda hesaplama gücünden tasarruf edebilirsiniz.
memoize (iterable $iterable): IteratorAggregate
Bir iterator'ın çevresine, dolaşma sırasında anahtarlarını ve değerlerini önbelleğe alan bir sargı oluşturur. Bu, özgün veri kaynağını yeniden dolaşmaya gerek kalmadan veriler üzerinde tekrar tekrar yineleme yapmayı sağlar.
$iterator = /* ... */; // birden çok kez dolaşılamayan veriler
$memoized = Iterables::memoize($iterator);
// Artık $memoized'i veri kaybı olmadan birden çok kez dolaşabilirsiniz
Bu metot, aynı veri kümesini birden çok kez dolaşmanız gereken ama özgün iterator'ın tekrar dolaşmaya izin vermediği ya da yeniden dolaşmanın maliyetli olduğu (örneğin verinin veritabanından veya dosyadan okunduğu) durumlarda işe yarar.
repeatable (callable $factory): IteratorAggregate
Normalde bunu desteklemeyen nesnelerin, tipik olarak PHP generator'larının tekrar tekrar dolaşılmasını
sağlar. repeatable() metodu bu sorunu şık bir şekilde çözer: iterator'ın kendisini aktarmak yerine, onu
oluşturan bir fonksiyon aktarırsınız. Bu factory, her yineleme döngüsünde otomatik olarak çağrılır.
// İki kez dolaşılamayan standart bir generator
$generator = function () {
yield 'A';
yield 'B';
};
$iterator = Iterables::repeatable($generator);
foreach ($iterator as $v) echo $v; // Yazdırır: AB
foreach ($iterator as $v) echo $v; // Yazdırır: AB (generator yeniden çalıştı)
Bu metot, büyük miktarda veriyle çalıştığınız durumlarda memoize() yerine
kullanılabilecek bir seçenektir; çünkü repeatable() veriyi önbelleğe almaz, her yinelemede yeniden
üretir.
some (iterable $iterable, callable $predicate): bool
Iterator'ın en az bir öğesinin $predicate ile tanımlanan koşulu sağlayıp sağlamadığını denetler.
$predicate callback'inin imzası function ($value, $key, iterable $iterable): bool şeklindedir ve
some() metodunun true döndürmesi için en az bir öğede true döndürmelidir.
$iterator = new ArrayIterator([1, 30, 39, 29, 10, 13]);
$isEven = fn($value) => $value % 2 === 0;
$res = Iterables::some($iterator, $isEven); // true
Bu metot, bir koleksiyondaki en az bir öğenin belirli bir koşulu karşıladığını hızlıca doğrulamak için kullanışlıdır; örneğin koleksiyonun en az bir çift sayı içerip içermediğini.
Bkz. every().
toIterator (iterable $iterable): Iterator
Herhangi bir iterable nesneyi (dizi, Traversable) bir Iterator'a dönüştürür. Girdi zaten bir Iterator ise değiştirilmeden döndürülür.
$array = [1, 2, 3];
$iterator = Iterables::toIterator($array);
// Artık dizi yerine bir Iterator'ınız var
Bu metot, girdi veri türünden bağımsız olarak elinizde bir Iterator bulunduğundan emin olmanız gerektiğinde işe yarar. Çeşitli iterable veri türleriyle çalışan fonksiyonlar yazarken yardımcı olabilir.