dictionarykotlinsyntaxfunctional-programmingpure-function

What is a more functional way of iteratively summing a list of values while capturing each intermediate result?


The code below works as expected, but the map lambda is impure. How could I refactor this to make it pure. (No need to stick to calling map, we could reduce or whatever else here, I just want it to be pure)

    val entries = listOf(
        Pair(LocalDate.now().minusDays(2), 1), 
        Pair(LocalDate.now().minusDays(1), 2), 
        Pair(LocalDate.now().minusDays(0), 3) 
    )

    private fun buildSumSchedule(entries: List<Pair<LocalDate, Double>>): Map<LocalDate, Double> {
        var runningSum = 0.0
        return entries.sortedBy { it.first }.map {
            runningSum += it.second
            it.copy(second = runningSum)
        }.toMap()
    }

    val sumSchedule = buildSumSchedule(entries)

Solution

  • what you want here is scanReduce that's how you can use the previous item after sorting

    @ExperimentalStdlibApi
    private fun buildSumSchedule(entries: List<Pair<LocalDate, Double>>): Map<LocalDate, Double> =
        entries.sortedBy { it.first }.scanReduce { pair, acc ->
            acc.copy(second = pair.second + acc.second)
        }.toMap()
    

    and from kotlin 1.4.0 runningReduce

    private fun buildSumSchedule(entries: List<Pair<LocalDate, Double>>): Map<LocalDate, Double> =
        entries.sortedBy { it.first }.runningReduce{acc, pair ->
            acc.copy(second = pair.second + acc.second)
        }.toMap()