ronak garg
ronak garg

Reputation: 5

How to use reduce function correctly with functional programming in kotlin

I am trying to pass a function and want to use reduce on it. This is the data class

data class TestClass(
   var variable1: BigDecimal?,
   var variable2: BigDecimal?
)

This is the function which I want to work

fun aggregateAll() {
   helperfunc(TestClass::variable1::get,someDummmyFilledListOfTestClass)
}

fun helperfunc(function: () ->BigDecimal, testList:List<TestClass>) {
     var aggregatedValue:BigDecimal = BigDecimal.ZERO
     testList.map{function}.reduce{aggregatedValue,element -> aggregatedValue.add(element)}
}

Upvotes: 0

Views: 169

Answers (2)

IR42
IR42

Reputation: 9672

fun main() {
    val someDummmyFilledListOfTestClass = listOf<TestClass>(
        TestClass(1.toBigDecimal()),
        TestClass(199.toBigDecimal()),
        TestClass(null),
        TestClass(501.toBigDecimal())
    )
    val result = helperfunc(someDummmyFilledListOfTestClass, TestClass::variable1::get)
                                                                 // trailing lambda
    // or val result = helperfunc(someDummmyFilledListOfTestClass) { it.variable1 }
    println(result)
}
                                         /* lambda last parameter for trailing lambda */
fun helperfunc(testList: List<TestClass>, function: (TestClass) -> BigDecimal?): BigDecimal {
    return testList
        // map TestClass to BigDecimal? and filter nulls
        .mapNotNull(function)
        // fold with initial value, reduce will throw exception if list is empty
        .fold(BigDecimal.ZERO) { acc, element -> acc.add(element) }
}

data class TestClass(
    var variable1: BigDecimal?
//  var variable2: BigDecimal?
)

Upvotes: 2

Tenfour04
Tenfour04

Reputation: 93581

For the map function to work, your function type needs a TestClass parameter, so it should be (TestClass) -> BigDecimal.

And your variable1 needs to be non-nullable, or it else its getter is a (TestClass) -> BigDecimal?, which doesn't match the required type.

And when you pass the function to map, don't wrap it in a lambda, because then you are just creating a function that returns your other function.

And you seem to want to use a separate aggregator rather than the first element of the list, so that means you should use fold instead of reduce.

data class TestClass(
    var variable1: BigDecimal,
    var variable2: BigDecimal?
)

fun aggregateAll() {
    helperfunc(TestClass::variable1::get, someDummmyFilledListOfTestClass)
}

fun helperfunc(function: (TestClass) -> BigDecimal, testList:List<TestClass>) {
    val sum: List<BigDecimal> = 
        testList.map(function).fold(BigDecimal.ZERO) { aggregatedValue, element -> aggregatedValue.add(element)}
}

Upvotes: 2

Related Questions