Bu iki işlevle oldukça kafam karıştı fold()ve reduce()Kotlin'de, biri bana her ikisini de ayıran somut bir örnek verebilir mi?
Bu iki işlevle oldukça kafam karıştı fold()ve reduce()Kotlin'de, biri bana her ikisini de ayıran somut bir örnek verebilir mi?
Yanıtlar:
fold bir başlangıç değeri alır ve ona ilettiğiniz lambda'nın ilk çağrısı, bu başlangıç değerini ve koleksiyonun ilk öğesini parametre olarak alır.
Örneğin, bir tamsayı listesinin toplamını hesaplayan aşağıdaki kodu alın:
listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
Lambda ilk çağrı parametreleri ile olacak 0ve 1.
İşleminiz için bir tür varsayılan değer veya parametre sağlamanız gerekiyorsa, bir başlangıç değerini iletme yeteneğine sahip olmak yararlıdır. Örneğin, bir listedeki maksimum değeri aradıysanız, ancak herhangi bir nedenle en az 10 döndürmek istiyorsanız, aşağıdakileri yapabilirsiniz:
listOf(1, 6, 4).fold(10) { max, element ->
if (element > max) element else max
}
reducebir başlangıç değeri almaz, bunun yerine biriktirici olarak koleksiyonun ilk öğesi ile başlar ( sumaşağıdaki örnekte çağrılır ).
Örneğin, tekrar bir tamsayı toplamı yapalım:
listOf(1, 2, 3).reduce { sum, element -> sum + element }
Burada lambda ilk çağrı parametreleri ile olacak 1ve 2.
Sen kullanabilirsiniz reducesizin işlem, bunu uyguluyorsanız koleksiyonunda dışında herhangi değerlere bağlı değildir zaman.
emptyList<Int>().reduce { acc, s -> acc + s }bir istisna oluşturacak, ancak emptyList<Int>().fold(0) { acc, s -> acc + s }sorun değil.
listOf<Int>(1, 2).reduce { acc: Number, i: Int -> acc.toLong() + i }(liste türü Int iken toplayıcı türü Sayı olarak bildirilir ve aslında bir
Söyleyeceğim en büyük işlevsel fark (diğer cevaptaki yorumlarda belirtilmiştir, ancak anlaşılması zor olabilir), boş bir koleksiyon üzerinde gerçekleştirilirse reduce bir istisna atacak olmasıdır .
listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.
Bunun nedeni .reduce, "veri olmaması" durumunda hangi değerin döndürüleceğini bilmemesidir.
Bunu .fold, boş bir koleksiyon olması durumunda varsayılan değer olacak bir "başlangıç değeri" sağlamanızı gerektiren şununla karşılaştırın :
val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)
Bu nedenle, koleksiyonunuzu farklı (ilgisiz) türden tek bir öğeye indirgemek istemeseniz bile (bu yalnızca .foldsize izin verir), başlangıç koleksiyonunuz boşsa, o zaman koleksiyonunuzu kontrol etmelisiniz. önce boyut ve sonra .reduceveya sadece kullanın.fold
val collection: List<Int> = // collection of unknown size
val result1 = if (collection.isEmpty()) 0
else collection.reduce { x, y -> x + y }
val result2 = collection.fold(0) { x, y -> x + y }
assertEquals(result1, result2)