Kotlin:将对象列表转换为对象属性映射

ozn*_*cro 4 lambda function kotlin

使用以下数据类:

data class Photo(val id: String)
data class Album(val id: String, val photos: List<Photo>)
Run Code Online (Sandbox Code Playgroud)

我希望能够将一个列表Albums变成一个地图Map<photoId, Set<albumId>>

例如:

val albums = listOf(
    Album("1", listOf(
        Photo("1"),
        Photo("2"),
        Photo("3")
    )),
    Album("2", listOf(
        Photo("1"),
        Photo("2")
    ))
)
Run Code Online (Sandbox Code Playgroud)

将转化为:

val map = mapOf(
    Pair("1", setOf("1", "2")),
    Pair("2", setOf("1", "2")),
    Pair("3", setOf("1")
)
Run Code Online (Sandbox Code Playgroud)

有没有办法使用 kotlin 转换函数/lambdas 来做到这一点?例如,groupBy、flatMap?

Oma*_*gra 5

更清洁的解决方案

val grouped = albums
    .flatMap { album -> album.photos.map { photo -> Pair(photo.id, album.id) } }
    .groupBy( { (photoId, _) -> photoId }, { (_, albumId) -> albumId } )
    .mapValues { it.value.toSet() }
Run Code Online (Sandbox Code Playgroud)

并检查正确性

val map = mapOf(
    Pair("1", setOf("1", "2")),
    Pair("2", setOf("1", "2")),
    Pair("3", setOf("1"))
)

check(map == grouped) // Success
Run Code Online (Sandbox Code Playgroud)

一点解释

  • 随着第一flatMap,我们改造的专辑列表(List<Album>在)List<Pair<String, String>>photo.idalbum.id)。

  • 使用groupBy我们将第二个列表转换Map<String, List<String>>为键所在的位置photo.id并按以下方式分组album..id

  • 随着mapValues我们将地图转换为Map<String, Set<String>>