我有一个问题。 我有以下课程
data class Item(val month: Int, val year: Int, val value: Int)
我有一个列表
val items = listOf(
Item(month = 1, year = 2019, value = 5000),
Item(month = 1, year = 2019, value = 200),
Item(month = 1, year = 2019, value = 300),
Item(month = 1, year = 2019, value = 1000),
Item(month = 2, year = 2019, value = 5000),
Item(month = 2, year = 2019, value = 6000),
Item(month = 3, year = 2019, value = 500),
Item(month = 3, year = 2019, value = 1500),
Item(month = 5, year = 2019, value = 900),
Item(month = 1, year = 2020, value = 700)
)
我想要对具有相同月份和年份的Item对象的值求和,并创建另一个以月,年和总和作为值的Item对象
val result = listOf(
Item(month = 1, year = 2019, value = 6500),
Item(month = 2, year = 2019, value = 11000),
Item(month = 3, year = 2019, value = 2000),
Item(month = 5, year = 2019, value = 900),
Item(month = 1, year = 2020, value = 700)
)
我该如何实现?谢谢
答案 0 :(得分:5)
首先,您按月+年分组(假设这应该是唯一的)。然后将其映射到一个新项目,其中值是每个组的值。
items.groupBy { "${it.month}/${it.year}" }
会给你这样的东西:
{
'01/2019': [
Item(month = 1, year = 2019, value = 5000),
Item(month = 1, year = 2019, value = 200),
Item(month = 1, year = 2019, value = 300),
Item(month = 1, year = 2019, value = 1000)
],
'02/2019': ...
}
您现在可以将此映射分组映射到新项目,在其中使用所有项目的总和重新计算value
。结果代码如下:
items.groupBy { "${it.month}/${it.year}" }
.map {
Item(it.value.first().month,
it.value.first().year,
it.value.sumBy(Item::value))
}
我的代码中的结果与示例输出完全一样。
更新:
为了避免字符串创建和访问第一个数组元素,有另一种方法。创建一个分组的数据对象:
data class Date(var month: Int, var year: Int)
现在,您可以按创建的Date对象分组-并解压缩值:
items.groupBy({ Date(it.month, it.year) }, { it.value })
这会创建一个像这样的地图:
{
{ month: 1, year: 2019 }: [ 5000, 200, 300, 1000 ],
{ month: 2, year: 2019 }: [ ... ]
}
此后,您可以按照与以前类似的方式对此进行映射,但具有更清晰的成员访问权限:
items.groupBy({ Date(it.month, it.year) }, { it.value })
.map {
Item(it.key.month,
it.key.year,
it.value.sum())
}
如果将其用作项目的基类,则还可以扩展数据类的重用。