Kotlin - 从两个集合中过滤/映射

jav*_*235 6 collections kotlin

是否可以根据所需的条件匹配过滤和映射两个集合,如下所示:

fun main(args: Array<String>) {
    val selectedDates = listOf("2018-08-12", "2018-08-13", "2018-08-14")

    val expenses = listOf(Expense("Food", "2018-08-12"),
    Expense("Transportation", "2018-08-15"),
    Expense("Misc.", "2018-08-13"),
     Expense("Uber", "2018-08-12"),
    Expense("Clothing", "2018-08-16"))

    val listOfExpensesInSelectedDate = mutableListOf<Expense>()

    for (date in selectedDates){
        listOfExpensesInSelectedDate.addAll(expenses.filter { it.date==date })

    }
    println(listOfExpensesInSelectedDate)

}

data class Expense(
        val expense:String,
        val date: String
)
Run Code Online (Sandbox Code Playgroud)

提供上面给定的代码,我试图返回与另一个字符串列表中的日期匹配的费用列表。在上面的例子中,我同时使用了循环和过滤函数来获得我想要的结果。但是是否可以在一行代码中避免 for 循环和过滤器并映射两个集合?

小智 7

你可以in用来过滤:

val listOfExpensesInSelectedDate = expenses.filter { it.date in selectedDates }
Run Code Online (Sandbox Code Playgroud)

编辑:由于热键发布了关于最佳解决方案的评论,我已经在我的电脑上尝试过这个,任何有兴趣的人也可以尝试一下:

(1)我发布的答案:

val start = Date().time
for (i in 1..10000) {
    val listOfExpensesInSelectedDate = expenses.filter { it.date in selectedDates }
}
val end= Date().time

println(end - start)
Run Code Online (Sandbox Code Playgroud)

平均时间结果:26ms(23ms-35ms)

(2nd)我用热键的建议回答使用一组:

val start = Date().time
for (i in 1..10000) {
    val expSet = selectedDates.toSet()
    val listOfExpensesInSelectedDate = expenses.filter { it.date in expSet }
}
val end= Date().time

println(end - start)
Run Code Online (Sandbox Code Playgroud)

平均时间结果:70ms(50ms-86ms)

(3d)热键的回答:

val start = Date().time
for (i in 1..10000) {
    val groups = expenses.groupBy { it.date }
    val listOfExpensesInSelectedDate = selectedDates.flatMap { groups[it].orEmpty() }
}
val end= Date().time

println(end - start)
Run Code Online (Sandbox Code Playgroud)

平均时间结果:100ms(74ms-150ms)


hot*_*key 5

您可以简化并通过第一分组优化你的代码expensesdate然后选择并合并有他们在关键的群体selectedDates,就像这样:

val selectedDates = listOf("2018-08-12", "2018-08-13", "2018-08-14")
val expenses: List<Expense> = TODO("content omitted")

val groups = expenses.groupBy { it.date }
val listOfExpensesInSelectedDate = selectedDates.flatMap { groups[it].orEmpty() }
Run Code Online (Sandbox Code Playgroud)

见:groupByflatMap