Home > database >  Kotlin - How to convert a list of objects into a single one after map operation?
Kotlin - How to convert a list of objects into a single one after map operation?

Time:01-19

I'm trying to wrap my head around map and reduce operations in Kotlin. At least, I guess it's reduce what I'm trying to do.

Let's say that I have a class called Car that takes any number (varargs constructor) of CarPart. Then, I have a list of CarPart which I'll do a map operation and from the result of the operation I need to build one Car using each subelement, something along these lines:

class CarPart(val description: String)
class Car(vararg val carPart: CarPart)

val carParts = listOf(CarPart("Engine"), CarPart("Steering Wheel")))

carParts.map { it.description.toUpperCase() }
    .map { CarPart(it) }
    .reduce { acc, carPart -> Car(carPart) }  <--- I'm struggling here, is reduce what I should be doing 
                                                   to construct one car from all the subelement?

PS.1: I know that the class design could be better and not take a varargs, this is just an example of a legacy application I'm refactoring and originally that's a Java class taking varargs which I can't change now.

PS.2: The example of mapping to a String and then creating an object out of that String is just for the sake of the example. The actual code grabs an object within the list.

CodePudding user response:

You can simply use a the spread operator (*) over an array:

val mappedCarParts = carParts
    .map { it.description.toUpperCase() }
    .map { CarPart(it) }
    .toTypedArray()

val car = Car(*mappedCarParts)

// Or even:

val car = carParts
    .map { it.description.toUpperCase() }
    .map { CarPart(it) }
    .toTypedArray()
    .let{ Car(*it) }

CodePudding user response:

You could just extract the constructor of the Car outside of the creation of the list. I don't see any reason as to why you'd want it inside.

val car = Car(
        *carParts
            .map { CarPart(it.description.uppercase(Locale.getDefault())) } //keep the .toUpperCase() if you are using an old version of Kotlin
            .toTypedArray()
    )

We need the spread operator there in order for the vararg to know that we are passing it the elements of the list and not the list itself.

  •  Tags:  
  • Related