Kotlin-基于和创建对象

时间:2019-05-19 11:42:14

标签: kotlin

我有一个问题。 我有以下课程

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)
)

我该如何实现?谢谢

1 个答案:

答案 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())
     }

如果将其用作项目的基类,则还可以扩展数据类的重用。

相关问题