Search code examples
kotlingroup-bycollections

Kotlin : Groupby the objects by 2 values, perform sum and then map it to other object


i am not very expert in kotlin collection functions so need some help: Assume i have a data class:

data class transaction(val SenderName: String,val ReceiverName: String,val Amount: Int)

the list of transactions

val transactions = listOf(
transaction("Rahul","Ravi",10000),
transaction("Rahul","Ravi",-500),
transaction("Ravi","Rahul",1000))

First i want to group the entries based on the sender & receiver followed by adding the amounts. which i am able to do using the below code

transactions.groupBy { it.SenderName to it.ReceiverName}.map{entity ->
 val amountSum = entity.value.sumOf { it.Amount }}

after this what i want is to calculate the final amount of transactions between 2 persons from one person's reference. Like for example i calculate for Rahul's point of view then: Sum of amount(where Rahul is Sender) - Sum of amount (where rahul is receiver) which will be: 9500 - 1000 = 8500 and the final output should be:

data class NewObject(val reference_person:String, val Other_person :String, val FinalAmount:Int)

val finalList = [("Rahul","Ravi",8500),("Ravi","Rahul",-8500)]

I have gone throught many stackoverflow posts but don't know how to achieve this. Thanks


Solution

  • You can try this

    val finalList = (transactions + transactions.map {
        transaction(
            it.ReceiverName,
            it.SenderName,
            -1 * it.Amount
        )
    }).groupBy { it.SenderName to it.ReceiverName }.map { entity ->
        NewObject(entity.key.first, entity.key.second, entity.value.sumOf { it.Amount })
    }
    
    println(finalList)
    //[NewObject(reference_person=Rahul, Other_person=Ravi, FinalAmount=8500), NewObject(reference_person=Ravi, Other_person=Rahul, FinalAmount=-8500)]
    

    What I first do is add to the original list the same list but with sender and receiver reversed. Then I group them like you did, and finally mapped them to NewObjects