aaaaahaaaaa
aaaaahaaaaa

Reputation: 452

Merging a list of maps (of list of string)

Baby Kotlin dev here :)

Considering the following structure:

[
  { "color": ["red", "blue"] },
  { "color": ["red", "green"] },
  { "shape": ["square", "circle"] },
  { "shape": ["rectangle"] }
]

I'd like to obtain the following results where keys and their respective values are merged:

[
  { "color": ["red", "blue", "green"] },
  { "shape": ["square", "circle", "rectangle"] }
]

After some research I was thinking of something like this (doesn't work/compile), but I'm missing some pieces:

val colors1 = mapOf("color" to listOf("red", "blue"))
val colors2 = mapOf("color" to listOf("red", "green"))
val shapes1 = mapOf("color" to listOf("square", "circle"))
val shapes2 = mapOf("color" to listOf("rectangle"))
var mainList = mutableListOf(colors1, colors2, shapes1, shapes2)

mainList.reduce { acc, it -> (acc.asSequence() + it.asSequence())
    .distinct()
    .groupBy({it.key}, {it.value})
    .mapValues { (_, values) -> values.flatten().distinct() }

Any help would be greatly appreciated.

Upvotes: 1

Views: 1848

Answers (1)

hotkey
hotkey

Reputation: 147901

Instead of merging the maps with reduce, you can use flatMap with the map entries. So it should work this way:

mainList
    .flatMap { it.entries }
    .groupBy({ it.key }, { it.value })
    .mapValues { (_, values) -> values.flatten().toSet() }

(runnable sample)

Also, a little bit more efficient way to flatten the values in the last line is:

    .mapValues { (_, values) -> values.flatMapTo(mutableSetOf()) { it } }

This removes the overhead of the intermediate collection that was created to store the values between flatten() and distinct()/toSet(), but still ensures that the items are unique because they are added to a mutableSet().


Sample with reassigning the mainList: (link)

Upvotes: 1

Related Questions