Home > Mobile >  Transform Map Values to Data Class in Kotlin
Transform Map Values to Data Class in Kotlin

Time:01-07

I have a map whose values are an arraylist of different object types (LocalDate, LocalTime, Float, List(Float)).

I would like to transform the map values to a custom data class i have created.

I have tried destructuring the maps value components however i am getting error "Destructuring declaration initializer of type Map.Entry<String, Any> must have a 'component3()' function".

How would i perform this transformation below?

Blockquote

    val localDate1 = LocalDate.now()
    val localTime1 = LocalTime.now()
    val float1 = 1f
    val floatList1 = listOf<Float>(1f, 2f, 3f)

    val localDate2 = LocalDate.now()
    val localTime2 = LocalTime.now()
    val float2 = 2f
    val floatList2 = listOf<Float>(4f, 5f, 6f)

    val myMap = HashMap<String, Any>()
    myMap["keyOne"] = arrayListOf<Any>(localDate1, localTime1, float1, floatList1)
    myMap["keyTwo"] = arrayListOf<Any>(localDate2, localTime2, float2, floatList2)

    val newMap = myMap.mapValues { (date, time, float, floatList) -> /*Here i am getting destructuring error*/
        CustomObject(
            date,
            time,
            float,
            floatList
        )
    }

Blockquote

data class CustomObject (
    val date: LocalDate,
    val time: LocalTime,
    val float: Float,
    val floatList: List<Float>
)

CodePudding user response:

Map.mapValues() takes a lambda whose receiver is the map Entry, not its value.  (The method is named for the lambda's results, not its parameter.) So you can't destructure it that way.

You could destructure it as a separate step, e.g.:

val newMap = myMap.mapValues { entry ->
    val (date, time, float, floatList) = entry.value
    CustomObject(
        date,
        time,
        float,
        floatList
    )
}

Or you could just use the array values directly:

val newMap = myMap.mapValues {
    CustomObject(
        it.value[0],
        it.value[1],
        it.value[2],
        it.value[3]
    )
}

However I think it would be better to avoid having the lists in the first place. Destructuring variable-length objects like lists and arrays is inherently risky (as they might not be long enough), and it looks like you're taking a lot of extra code to create the lists and then convert them. If there's any way you can create your custom objects directly, that's likely to be shorter, safer, and easier to read.

CodePudding user response:

import java.time.LocalDate
import java.time.LocalTime

data class CustomObject(
  val date: LocalDate,
  val time: LocalTime,
  val float: Float,
  val floatList: List<Float>
)

val myMap = mapOf(
  "keyOne" to listOf(LocalDate.now(), LocalTime.now(), 1f, listOf(1f, 2f, 3f)),
  "keyTwo" to listOf(LocalDate.now(), LocalTime.now(), 2f, listOf(4f, 5f, 6f))
)

val newMap = myMap.mapValues {
  CustomObject(
    it.value[0] as LocalDate,
    it.value[1] as LocalTime,
    it.value[2] as Float,
    (it.value[3] as List<*>).map { fl -> fl as Float }
  )
}

println(newMap)
  •  Tags:  
  • Related