Reduce mekanizması, veri koleksiyonları üzerindeki fonksiyonel işlemlere aittir ve Swift'e fonksiyonel dillerden (map-reduce, fold) gelmiştir. Tarihsel olarak, bu fonksiyon, herhangi bir koleksiyonu tek bir agregat değere dönüştürmek için kullanılır (örneğin, toplam, çarpım, string'lerin birleştirilmesi vb.), tüm elemanları geçerek sonucu biriktirir. Çözmeye çalıştığı temel sorun — verilerin el ile döngüler kullanmadan yalın, okunabilir ve hatasız bir şekilde agregasyonudur.
Swift'te reduce, koleksiyonların bir metodu olarak tanımlanmıştır:
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
Bu, başlangıç (ilk) değeri belirlemeniz gerektiği anlamına gelir, ardından her bir eleman için ve mevcut akümülatör için yeni bir agregate değer döndüren bir fonksiyon yazarsınız.
Kod örneği:
let numbers = [1, 2, 3, 4] let sum = numbers.reduce(0) { $0 + $1 } // 10 let joined = numbers.reduce("") { $0 + String($1) } // "1234"
Anahtar özellikler:
Boş bir koleksiyonda reduce nasıl çalışır?
Reduce, koleksiyonun her bir elemanına uygulanır. Eğer koleksiyon boşsa — başlangıç (ilk) değeri döndürülür, kapama çağrılmayacaktır.
Kod örneği:
let empty: [Int] = [] let sum = empty.reduce(100) { $0 + $1 } // 100
Reduce ile başlangıç koleksiyonunu değiştirmek mümkün mü?
Hayır, reduce — saf bir fonksiyondur, başlangıç koleksiyonunu değiştirmez. Tüm değişiklikler yalnızca akümülatörde gerçekleşir.
Reduce ve reduce(into:) arasındaki fark nedir?
reduce(into:), akümülatörü her geçişte değiştirmeyi sağlar ve değer türleriyle (value-types) çalıştığında daha verimli olur; yeni bir kopya oluşturmak (copy-on-write) maliyetlidir.
Kod örneği:
let nums = [1, 2, 3] let squares = nums.reduce(into: []) { (result: inout [Int], item) in result.append(item * item) } // squares == [1, 4, 9]
Geliştirici, products dizisindeki ürünlerin fiyatlarını toplamak istedi. Başlangıç değeri 0.0 olan reduce kullandı, ancak closure öyle ayarlanmıştı ki bazen indirimler olduğunda negatif bir toplam döndürüyor, bu da hatalı sonuçlara ve vergi hesaplama sorunlarına yol açtı.
Artılar:
Eksiler:
id'ye göre varlıklar dizisinden bir önbellek oluşturmak için reduce(into:) kullanıldı:
let objects: [Entity] = ... let cache = objects.reduce(into: [:]) { $0[$1.id] = $1 }
Artılar:
Eksiler: