Как скопировать свойство между 2 списками разных типов, используя декларативный Kotlin? - PullRequest
0 голосов
/ 05 февраля 2019

Контекст

При использовании декларативного подхода в Kotlin необходимо скопировать одно свойство name из List из User объектов в List из UserDetail объектов на основе сопоставления id свойства, как показано ниже:

val users = Arrays.asList(
        User(1, "a"),
        User(2, "b")
)
val details = Arrays.asList(
        UserDetail(1),
        UserDetail(2)
)
val detailsWithName = copyNameToUser(users, details)

Модели:

class User {
    var id = -1;
    var name = "" // given for all Users
    constructor(id: Int, name: String)
    // ...
}
class UserDetail {
    var id = -1;
    var name = "" // blank for all UserDetails
    constructor(id: Int)
    // ...
}

Задача

Попытка использовать декларативный подход с помощью итерационной функции forEach:

fun copyNameToDetails(users: List<User>, details: List<UserDetail>): List<UserDetail> {
    details.forEach(d ->
        users.forEach(u ->
            if (d.id == u.id) {
                d.name = u.name
            }
        )
    )
    return details
}

Это может быть достигнуто в Java, как показано ниже:

private static List<UserDetail> copyNameToDetails(List<User> users, List<UserDetail> details)   {
    for (UserDetail d: details) {
        for (User u : users) {
            if (d.id == u.id) {
                d.name = u.name;
            }
        }
    }
    return details;
}

Вопрос

Как это можно сделать в Kotlin, используя декларативный подход?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Другой подход с неизменяемыми значениями:

data class User(val id: Int = -1, val name: String = "")
data class UserDetail(val id: Int = -1, val name: String = "")

private fun List<UserDetail>.copyNameToUser(users: List<User>): List<UserDetail> = map { userDetail ->
    users.firstOrNull { userDetail.id == it.id }?.let { userDetail.copy(name = it.name) } ?: userDetail
}
0 голосов
/ 05 февраля 2019

Вы делаете слишком много итераций по обоим спискам (users.size * details.size), поэтому при создании хэш-карты это можно исправить:

fun copyNameToUsers(users: List<User>, details: List<UserDetail>): List<UserDetail> {
    val usersById = users.associate { it.id to it }
    details.forEach { d ->
        usersById[d.id]?.let { d.name = it.name }
    }

    return details
}
...