Collections 使用多个对象字段/多个条件筛选ArrayList
因此,我在筛选集合时遇到了一个有趣的问题,我有一个数据类,如下所示:Collections 使用多个对象字段/多个条件筛选ArrayList,collections,filter,kotlin,Collections,Filter,Kotlin,因此,我在筛选集合时遇到了一个有趣的问题,我有一个数据类,如下所示: data class Route( val id: Int, val name: String, val weeklyPrice: Double?, val monthlyPrice: Double?, val seasonalPrice: Double?, ) 我在UI中显示一个ArrayList,用户可以根据路线是否有“周/月/季”价格筛选列表,请记住我使用的是复选框而不是单选按钮
data class Route(
val id: Int,
val name: String,
val weeklyPrice: Double?,
val monthlyPrice: Double?,
val seasonalPrice: Double?,
)
我在UI中显示一个ArrayList,用户可以根据路线是否有“周/月/季”价格筛选列表,请记住我使用的是复选框而不是单选按钮,因此用户可以使用多个选项进行筛选。即,仅每周,或每周和每月,等等
我的问题是,使用filter函数和谓词一次只能基于一个属性进行筛选,如下所示:
routes.filter {
it.weeklyPrice != null
}
但有时我会根据另一个条件过滤掉我想要保留的值,例如,用户不想要每周价格的路线,所以我过滤掉这些,但他想要每月价格的路线,但其中一些已经被过滤掉了,因为它们也有周价格
任何帮助都将不胜感激,我相信这是可以做到的我只是还没有弄清楚如何,也许问题在于数据首先是如何表示的?我不确定
非常感谢。如果要保留值,请缓存所有路由,然后过滤它们:
val allRoutes = ... // somewhere initialized
val filtered = allRoutes.filter {
it.monthlyPrice != null
}
// use filtered routes, but keep reference to allRoutes
一种方法是生成一个过滤器列表,例如,
list Boolean>
,然后只要过滤器列表发生更改,就可以使视图无效
例如,你有这样的东西:
// Use your own logic based on user selection here
private fun generateFilters() = listOf<(Route) -> Boolean>(
{ it.id != 0 },
{ it.weeklyPrice != null }
)
private fun <T> List<T>.filterAll(filters: List<(T) -> Boolean>) =
filter { item -> filters.all { filter -> filter(item) } }
然后您的视图逻辑就变成:
routers.filterAll(generateFilters())
好吧,这就是我最后要做的。。在看到上面@kcopock的答案之前,我就这么做了 我使用一个可变集来保存我主动想要向用户显示的所有路由,并使用以下代码来侦听每个框的所有CheckedChanged事件:
view.cb_weekly.setOnCheckedChangeListener { _, isChecked ->
weeklyIncluded = isChecked
if (weeklyIncluded) {
activeRoutes.addAll(routes.filter { route ->
route.weeklyPrice != null
})
} else {
activeRoutes.removeAll(routes.filter { route ->
route.weeklyPrice != null && route.monthlyPrice == null && route.seasonalPrice == null
})
if (!monthlyIncluded && seasonalIncluded) {
activeRoutes.removeAll(routes.filter { route ->
(route.weeklyPrice != null || route.monthlyPrice != null) && route.seasonalPrice == null
})
} else if (!seasonalIncluded && monthlyIncluded) {
activeRoutes.removeAll(routes.filter { route ->
(route.weeklyPrice != null || route.seasonalPrice != null) && route.monthlyPrice == null
})
} else if (!seasonalIncluded && !monthlyIncluded) {
activeRoutes.clear()
}
}
drawRoutes(activeRoutes)
}
请记住,我标记为正确的答案(不是这一个)可能是更好的方法。非常感谢您的帮助,我可能最终会重构代码,以使用上面的方法,这可能会提高性能。
view.cb_weekly.setOnCheckedChangeListener { _, isChecked ->
weeklyIncluded = isChecked
if (weeklyIncluded) {
activeRoutes.addAll(routes.filter { route ->
route.weeklyPrice != null
})
} else {
activeRoutes.removeAll(routes.filter { route ->
route.weeklyPrice != null && route.monthlyPrice == null && route.seasonalPrice == null
})
if (!monthlyIncluded && seasonalIncluded) {
activeRoutes.removeAll(routes.filter { route ->
(route.weeklyPrice != null || route.monthlyPrice != null) && route.seasonalPrice == null
})
} else if (!seasonalIncluded && monthlyIncluded) {
activeRoutes.removeAll(routes.filter { route ->
(route.weeklyPrice != null || route.seasonalPrice != null) && route.monthlyPrice == null
})
} else if (!seasonalIncluded && !monthlyIncluded) {
activeRoutes.clear()
}
}
drawRoutes(activeRoutes)
}