我有一个对象列表A(alist
)。
A {
val b : Int
val c1 : Int
val c2 : Int
val d1 : Int
val d2 : Int
}
我希望按b
对它们进行分组,并计算每个组c1+c2
和d1+d2
的总和,并将结果放入E对象列表elist
。
E {
val sum_of_c_types : Int
val sum_of_d_types : Int
}
如何使用任何内置功能集合在kotlin中实现?
请注意:
我知道我可以使用reduce
函数来创建临时A对象,但这对于在代码中不使用临时A对象很重要。
答案 0 :(得分:5)
我使用groupBy
,map
和sumBy
的序列解决了这个问题。它可能不是我猜的最干净的解决方案。
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}")
}
}
结果:
Group b=1: E(sumC=10, sumD=18)
Group b=2: E(sumC=4, sumD=4)
Group b=3: E(sumC=3, sumD=3)
修改强>:
使用Grouping
(使用groupingBy
代替groupBy
),它看起来更好,因为您不必处理地图实体:
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)
}
答案 1 :(得分:2)
我认为它只是用折叠分组
fun group(a: List<A>) = a.groupingBy(A::b).fold(E(0, 0),
{ acc, elem ->
E(acc.sum_of_c_types + elem.c1 + elem.c2,
acc.sum_of_d_types + elem.d1 + elem.d2)
})
答案 2 :(得分:1)
我通过以下代码解决了这个问题:
alist.groupby { b }. mapValues {
it.value.map {
E(it.c1+it.c2, it.d1+it.d2)
}.reduce {
acc, e -> E(acc.sum_of_c_types + e.sum_of_c_types, acc.sum_of_d_types + e.sum_of_d_types)
}.values