Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to merge values from different (but similar) objects in list in Kotlin?

Tags:

kotlin

Ok, so I have a list<SomeObject>

class SomeObject(
  val number: Int,
  val otherNumber: Int,
  val list<OtherObject>
)

The objects in the list can have same number and otherNumber but different values in their list<OtherObject>

I want to merge every object in the list with the same number and otherNumber. So for example if I have a list<SomeObject> with 3 entries:

1 = SomeObject(1, 1, list<OtherObject>

2 = SomeObject(1, 1, list<OtherObject>

3 = SomeObject(1, 2, list<OtherObject>

I would want entry 1 and 2 to become one list entry with the values of both lists combined.

I can do this with a lot of looping and stuff, however the list is super long and I cannot seem to do it in an efficient manner.

Is there some kotlin function for this? Or do anyone have a good suggestion as to how I should approach it?

like image 381
Skrettinga Avatar asked Sep 07 '25 01:09

Skrettinga


1 Answers

Maybe this would be a fitting solution for you. Instead of List<OtherObject> I used a List<String> but that should not make a difference.

You might want to consider wrapping your List<SomeObject> into a Sequence to build up a filter that is executed all at once instead of actually applying groupBy and so on to the List. Also refer https://kotlinlang.org/docs/sequences.html

For explaination please check the comments in the code.

fun main() {
    val objects = listOf(
            SomeObject(1, 1, listOf("a")),
            SomeObject(1, 1, listOf("b")),
            SomeObject(1, 2, listOf("c")))


    // group all objects by number and othernumber (both have to match)
    val grouping = objects.groupBy { Pair(it.number, it.otherNumber) }

    // consolidate a grouping onto a new object, so
    // [Pair(1,1), List(SomeObject(1,1,["a","b"]), SomeObject(1,1,["c","d"])) ]
    // [Pair(2,1), List(SomeObject(2,1,["e","f"]), SomeObject(2,1,["g","h"])) ]
    // becomes
    // List(SomeObject(1,1,["a","b", "c", "d"]), SomeObject(2,1,["e","f", "g", "h"]))
    val consolidated = grouping.values.map {
        objectsWithSameNumber ->
        SomeObject(objectsWithSameNumber[0].number,
                   objectsWithSameNumber[0].otherNumber,
                   objectsWithSameNumber.flatMap { it.list })
    }

    /*
    1 1: [a, b]
    1 2: [c]
     */
    for (result in consolidated) {
        println(result)
    }
}

class SomeObject(
        val number: Int,
        val otherNumber: Int,
        val list: List<String>
){
    override fun toString(): String {
        return "$number $otherNumber: $list"
    }
}
like image 175
Dominik Avatar answered Sep 08 '25 13:09

Dominik