从列表列表创建地图

use*_*930 3 kotlin

我想从列表列表创建地图,我已经编写了这段代码

fun getCourses(coursesCount: Int): Map<Course, Int> {
    val paidCourses = mutableMapOf<Course, Int>()
    for(student in data) {
                for(course in student.subscribedCourses) {
                    if( course.isPaid ) {
                        paidCourses.putIfAbsent(course, 0)
                        paidCourses[course] = paidCourses[course]!! + 1
                    }
                }
            }
    return paidCourses.toList().sortedByDescending { (_, value) -> value }.take(coursesCount).toMap()
}
Run Code Online (Sandbox Code Playgroud)

我想知道如何在 Kotlin 中更简洁地表达这一点。

Swe*_*per 5

您可以将flatMap“有课程的学生”扁平化为所有课程的单个列表,filterisPaid,按每门课程分组,并用于eachCount对课程进行计数。

val paidCourses = 
    data.flatMap { it.subscribedCourses }
        .filter { it.isPaid }
        .groupingBy { it }.eachCount()
Run Code Online (Sandbox Code Playgroud)

请注意,这将创建多个中间列表并多次循环它们,这可能是不可取的。这是一种避免这种情况的方法,而且仍然非常简洁:

val paidCourses = mutableMapOf<Course, Int>()
for(student in data) {
    for(course in student.subscribedCourses) {
        if (course.isPaid) {
            paidCourses.merge(course, 1, Int::plus)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以这样做:

val paidCourses = mutableMapOf<Course, Int>()
for(student in data) {
    student.subscribedCourses.filter { it.isPaid }
        .groupingBy { it }
        .eachCountTo(paidCourses)
}
Run Code Online (Sandbox Code Playgroud)