I have a list of objects A (alist
).
A {
val b : Int
val c1 : Int
val c2 : Int
val d1 : Int
val d2 : Int
}
and I want to group them by b
and calculate sum of c1+c2
and d1+d2
on each group and put the results in list of E objects elist
.
E {
val sum_of_c_types : Int
val sum_of_d_types : Int
}
How do I achieve in kotlin using any collection inbuilt function?
note:
I know I can do it with reduce
function and create temporary A objects, but this is important to dont use temporary A object in code.
Groups elements from the Grouping source by key and applies operation to the elements of each group sequentially, passing the previously accumulated value and the current element as arguments, and stores the results in a new map. The key for each element is provided by the Grouping. keyOf function.
A simple solution to calculate the sum of all elements in a List is calling the sum() function. It is available for a list of all numeric data types. i.e, Int , Long , Float , Double , Byte , Short . Note that as of Kotlin 1.5, sumBy() function is deprecated.
The Kotlin standard library provides extension functions for grouping collection elements. The basic function groupBy() takes a lambda function and returns a Map . In this map, each key is the lambda result and the corresponding value is the List of elements on which this result is returned.
The Kotlin standard library provides extension functions for grouping collection elements. The basic function groupBy () takes a lambda function and returns a Map. In this map, each key is the lambda result and the corresponding value is the List of elements on which this result is returned.
Note that as of Kotlin 1.5, sumBy () function is deprecated. You should use the sumOf () function instead. Alternatively, you can transform each object of the element to the corresponding field using the map () function. Finally, return the sum using the sum () function.
How groupBy works in Kotlin? The groupby function is one of the built-in functions to perform the grouping operations with the specific data that can be achieved using the customized filters even though it can be applied in the data.
The basic function groupBy () takes a lambda function and returns a Map. In this map, each key is the lambda result and the corresponding value is the List of elements on which this result is returned. This function can be used, for example, to group a list of String s by their first letter.
I've solved it by using a sequence of groupBy
, map
and sumBy
. It's probably not the cleanest solution I guess.
data class A(val b: Int,
val c1: Int,
val c2: Int,
val d1: Int,
val d2: Int)
data class E(val sumC: Int, val sumD: Int)
fun main(args: Array<String>) {
val alist = listOf(A(1, 2, 1, 4, 5), A(1, 3, 4, 6, 3), A(2, 2, 2, 2, 2), A(3, 1, 2, 1, 2))
val grouped: Map<Int, E> = alist.groupBy(A::b).mapValues {
E(it.value.sumBy { it.c1 + it.c2 }, it.value.sumBy { it.d1 + it.d2 })
}
grouped.forEach {
println("Group b=${it.key}: ${it.value}")
}
}
Results in:
Group b=1: E(sumC=10, sumD=18)
Group b=2: E(sumC=4, sumD=4)
Group b=3: E(sumC=3, sumD=3)
Edit:
With Grouping
(using groupingBy
instead of groupBy
), it looks even better because you don't have to handle map entities:
val grouped = alist.groupingBy(A::b).aggregate { _, acc: E?, e, _ ->
E((acc?.sumC ?: 0) + e.c1 + e.c2, (acc?.sumD ?: 0) + e.d1 + e.d2)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With