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 0
ve 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
}
reduce
bir başlangıç değeri almaz, bunun yerine biriktirici olarak koleksiyonun ilk öğesi ile başlar ( sum
aş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 1
ve 2
.
Sen kullanabilirsiniz reduce
sizin 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 .fold
size izin verir), başlangıç koleksiyonunuz boşsa, o zaman koleksiyonunuzu kontrol etmelisiniz. önce boyut ve sonra .reduce
veya 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)