Lucas P.
Lucas P.

Reputation: 4532

Kotlin: How can I reduce child arrays into a single array?

I have a pice of code in Swift that reduces a list of TVSchedule objects into an array of TVMatch pobjects. Each TVSchedule, has a property called events, that is a list of TVMatches.

The code in swift is the following:

var matches: [TVMatch] {
    let slots = timeSlots.reduce(into: [TVMatch]()) { (result, schedule) in
        result.append(contentsOf: schedule.events)
    }
    return slots
}

I'm trying to do the same reduce in Kotlin and the code I have is the following:

val matches: ArrayList<TVMatch>
    get() {
        val slots = timeSlots.fold(arrayListOf<TVMatch>()) { result, schedule ->
            result.addAll(schedule.events)
        }
        return slots
    }

However, the Kotlin code gives me a type error, and does not compile. What is the problem here?

Upvotes: 1

Views: 844

Answers (2)

Roland
Roland

Reputation: 23262

addAll returns a boolean, but the return value of the fold-operation should be of same type as the given initial object (in this case ArrayList). You can solve that one easily by just adding result after your addAll-statement, e.g.:

result.addAll(schedule.events)
result // this is now the actual return value of the fold-operation

Alternatively just use apply or similar instead:

result.apply {
  addAll(schedule.events)
} // result is the return value then

Note that you can actually simplify altogether using flatMap to just (side-note: if you use this approach the matches are evaluated only once of course, but flatMap is the star here anyway ;-))):

val matches = timeSlots.flatMap { it.events } // this is a new list! (note, if you do several mappings in a row, you may want to use timeSlots.asSequence().flatMap { }.map { }.toList() / or .toMutableList() instead

Alternatively if you really require the matches to be of type ArrayList, use flatMapTo instead:

val matches = timeSlots.flatMapTo(ArrayList()) { it.events }

You can of course keep the get() if you must, or just move the getting of the matches to its own function, e.g.:

fun getMatches() = timeSlots.flatMapTo(ArrayList()) { it.events }

Upvotes: 5

EpicPandaForce
EpicPandaForce

Reputation: 81539

Am I crazy, or can't you just replace the code with

val matches: List<TVMatch>
    get() = timeSlots.flatMap { schedule -> schedule.events }

?

Upvotes: 4

Related Questions