Kotlin - How to update particular value from a list of data class

Viewed 4074

I have a data class of Worker,

data class Worker(val id: Int, val name:String, val gender :String, val age :Int, val tel:String,val email:String)

and a list of workers

List<Worker> = listOf(workerA, workerB)

I want to write a function to update the data of Worker, e.g.:

updateWorkerData(1, age, 28)

//'type' refer to name, gender, age ..
//'value' refer AA, Female, 27 ..
fun updateWorkerData(id: Int, type: Any, value: Any) {
  val workers = getListOfWorker()
  workers.forEach {
  if (it.id == id) {
   //here is where I stuck    
  }    
}
}

I'm stuck on how to refer the type to the value in Data class Worker. Need some guide on how to update the Worker's data. Thanks.

3 Answers

Your data class should have mutable properties, so that they can be changed:

data class Worker(val id: Int, var name: String, var gender: String, var age: Int, var tel: String, var email: String)

Then you can pass out the KProperty to the function that can change that propety:

fun <T> updateWorkerData(id: Int, property: KMutableProperty1<Worker, T>, value: T) {
    val workers = getListOfWorker()
    workers.forEach {
        if (it.id == id) {
            property.set(it, value)
        }
    }
}

updateWorkerData(1, Worker::age, 28)

I would prefer to use immutability instead of using mutable fields for a data class.

A simple solution is the following:

fun List<Worker>.updateWorkerDataAge(id: Int, age: Int): List<Worker> =
        this.map { worker -> if (worker.id == id) worker.copy(age = age) else worker }

and you can use it:

val newWorkerList = workerList.updateWorkerDataAge(2, 99)

Animesh's answer is correct, I just wanted to point out that it may be simpler to use a Map of Workers (where the key is the worker ID), and just edit the workers directly, rather than doing clever (and difficult to understand) things with reflection:

val workers: Map<Int, Worker> = listOf(
    Worker(1, "a", "a", 1, "a", "a"),
    Worker(2, "b", "b", 2, "b", "b"),
    Worker(3, "c", "c", 3, "c", "c"),
).map { it.id to it }.toMap()

// Worker 1 changes name
workers.getValue(1).name = "Slartibartfast"

// Worker 2 gets older
workers.getValue(2).age += 1

// Worker 3 changes email
workers.getValue(3).email = "newemail@example.com"
Related