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

时间:2018-12-12 05:07:31

标签: function lambda kotlin

具有以下数据类:

data class Photo(val id: String)
data class Album(val id: String, val photos: List<Photo>)

我希望能够将Albums的列表转换为Map<photoId, Set<albumId>>的地图

例如:

val albums = listOf(
    Album("1", listOf(
        Photo("1"),
        Photo("2"),
        Photo("3")
    )),
    Album("2", listOf(
        Photo("1"),
        Photo("2")
    ))
)

将转换为:

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

有没有一种方法可以使用kotlin转换函数/ lambdas?例如,groupBy,flatMap?

2 个答案:

答案 0 :(得分:3)

清洁剂溶液

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

并检查正确性

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

check(map == grouped) // Success

一些解释

  • 使用第一个flatMap,将{em}列表(List<Album>)从List<Pair<String, String>>photo.id转换为{{1 }}。

  • 使用album.id,我们将第二个列表转换成groupBy,其中键为Map<String, List<String>>并按photo.id

  • 分组
  • 使用album..id将地图转换为mapValues

答案 1 :(得分:0)

肮脏的解决方案:

val map = albums.map {
    it.photos.map { it.id } // get all photos in all album
}.flatten() // into a single list (instead of 2-d list)
    .toSet() // remove duplicates
    .associate { photo ->
        photo to albums.filter { it.photos.contains(Photo(photo)) } // for each photo, find its existance in all albums
            .map { it.id }.toSet() // output album ids
    }
相关问题