Home > Software design >  Kotlin - switching object detail based on group by
Kotlin - switching object detail based on group by

Time:12-17

For example I have a class with below json format

[
    {
        "name": "a",
        "detail": [
            "1",
            "2",
            "3"
        ]
    },
    {
        "name": "b",
        "detail": [
            "2",
            "3",
            "4"
        ]
    }
]

how to change grouped it based on the detail?

[
    {
        "detail": "1",
        "name": [
            "a"
        ]
    },
    {
        "detail": "2",
        "name": [
            "a",
            "b"
        ]
    },
    {
        "detail": "3",
        "name": [
            "a",
            "b"
        ]
    },
    {
        "detail": "4",
        "name": [
            "b"
        ]
    }
]

below is my class structure

data class funName(
    @field:JsonProperty("name")
    val name: String = "",

    @field:JsonProperty("detail")
    val detail: Array<String> = arrayOf(""),

)

and my object is based on the array of funName

val data: Array<funName> = ...

i really have no idea how to do it.

val convert = data.groupBy { x -> x.detail  } ??

Is this doable in kotlin/java?

CodePudding user response:

Since the original data is grouped by name, you can think of the original data as a list of pairs

name detail
a    1
a    2
a    3
b    2
b    3
b    4

Mapping it to this format first would make it very easy to group by the second thing (detail) in the pair.

Since each funName corresponds to multiple pairs like this, you should use flatMap on data.

val result = data.flatMap { funName -> 
        funName.detail.map { funName.name to it } 
    }
    .groupBy(keySelector = { (name, detail) -> detail }, valueTransform = { (name, detail) -> name })
    // or more concisely, but less readable
    // .groupBy({ it.second }) { it.first }

This will get you a Map<String, List<String>>.

If you want a List<Result>, where Result is something like

data class Result(
    val detail: String = "",
    val names: List<String> = listOf(),
)

You can add an additional map:

.map { (k, v) -> Result(k, v) }
  • Related