首页 > 解决方案 > 更新 Kotlin 中特定键的映射值

问题描述

我是 Kotlin 的新手,正在努力赶上这门语言。

我有一个函数返回 DayofWeek 作为键和 Int 作为值。

我面临的问题是我需要获取一个对象列表,其中包含另一个对象列表,其中包含一个 Int 值,每次看到相同的值时我都需要保存和递增该值。

这是我的功能-

class OrdersAnalyzer {
    data class Order(val orderId: Int, val creationDate: LocalDateTime, val orderLines: List<OrderLine>)

    data class OrderLine(val productId: Int, val name: String, val quantity: Int, val unitPrice: BigDecimal)


    fun totalDailySales(orders: List<Order>) : Map<DayOfWeek, Int> {
        val map: MutableMap<DayOfWeek, Int>? = mutableMapOf(
            Pair(DayOfWeek.SUNDAY, 0),
            Pair(DayOfWeek.MONDAY, 0),
            Pair(DayOfWeek.TUESDAY, 0),
            Pair(DayOfWeek.WEDNESDAY, 0),
            Pair(DayOfWeek.THURSDAY, 0),
            Pair(DayOfWeek.FRIDAY, 0),
            Pair(DayOfWeek.SATURDAY, 0)
        )
        for (order in orders) {
            val dayOfWeek = order.creationDate.dayOfWeek
            var quantity = 0

            map?.put(dayOfWeek, quantity)
        }
        return map!!
    }

}

所以我现在面临的问题是2 -

1)当它是正确的 DayOfWeek 时,如何增加每对的值?我不想替换,我想将它添加到最后一个值。

2)返回地图时,我不想返回值为 0 的 DayOfWeeks。我该怎么做?

标签: dictionarykotlin

解决方案


这是Arjan提供的优雅答案的修改版本,带有一些测试代码。

在Alon Shlider发表评论后更新了答案——现在计算按星期几分组的所有订单项目数量:

fun totalDailySales(orders: List<Order>): Map<DayOfWeek, Int> =
    orders.groupBy { it.creationDate.dayOfWeek }
        .mapValues { sumItemQuantities(it.value) }

fun sumItemQuantities(orders: List<Order>) =
    orders.flatMap { it.orderLines.map { line -> line.quantity } }.sum()

fun main() {
    val orders = listOf(
        Order(
            1,
            LocalDateTime.now().minusDays(2),
            listOf(
                OrderLine(6, "laptop", 28, 1200.toBigDecimal())
            )
        ),
        Order(
            2,
            LocalDateTime.now().minusDays(1),
            listOf(
                OrderLine(496, "VR headset", 6, 400.toBigDecimal())
            )
        )
    )

    println(totalDailySales(orders))
}

输出:

{FRIDAY=28, SATURDAY=6}

使用这种方法,Kotlin 函数会为您进行分组和计数。groupBy 函数创建从 DayOfWeek 到订单列表的映射(将列表中具有同一星期几的所有订单分组)。mapValues 函数通过将列表替换为 sumItemQuantities 函数的结果(对于每个列表)来转换该映射。

在代码的 for 循环中,您可以检索特定日期的当前数量(如果尚未设置,则使用零),将其增加适当的数量,然后存储它。要仅返回具有非零值的地图条目,您可以过滤(返回 totalsPerDay.filter { it.value > 0 })或从空地图开始。这是您的功能,有一些更改:

fun totalDailySales(orders: List<Order>): Map<DayOfWeek, Int> {
    val totalsPerDay = mutableMapOf<DayOfWeek, Int>()

    for (order in orders) {
        val dayOfWeek = order.creationDate.dayOfWeek
        val currentQuantity = totalsPerDay[dayOfWeek] ?: 0

        // This is not the best way to increment by the sum of the order
        // item quantities...
        val orderItemQuantities = sumItemQuantities(listOf(order))
        totalsPerDay[dayOfWeek] = currentQuantity + orderItemQuantities
    }

    return totalsPerDay
}

调用后输出:

println(OrdersAnalyzer().totalDailySales(orders))

{FRIDAY=28, SATURDAY=6}

推荐阅读