所以我在过滤集合时遇到了一个有趣的问题,我有一个如下的数据类:
data class Route(
val id: Int,
val name: String,
val weeklyPrice: Double?,
val monthlyPrice: Double?,
val seasonalPrice: Double?,
)
我在UI中显示ArrayList,用户可以根据路线是否具有“每周/每月/季节性”价格过滤列表,请记住我使用的是复选框而不是单选按钮,因此用户可以使用多个选项进行过滤。即。仅每周一次,或者每周和每月一次,等等。
我的问题是,使用过滤器功能和谓词,我一次只能基于一个属性进行过滤,
routes.filter {
it.weeklyPrice != null
}
但是有时候我实际上会根据其他条件过滤掉我想保留的值,例如,某个用户不希望使用每周价格的路线,因此我将其过滤掉,但他想要使用每月价格的那些,但其中一些已基于它们也具有每周价格的事实而被过滤掉。
任何帮助将不胜感激,我确定可以做到,但我还没有弄清楚如何做,也许问题出在首先是如何表示数据?我不确定。
非常感谢。
答案 0 :(得分:1)
一种方法是生成过滤器列表,例如List<(Route) -> Boolean>
,然后只要过滤器列表更改,就使视图无效。
例如,您有类似的东西:
// Use your own logic based on user selection here
private fun generateFilters() = listOf<(Route) -> Boolean>(
{ it.id != 0 },
{ it.weeklyPrice != null }
)
然后,您的视图是基于这组过滤器生成的,即:
private fun filterRoutes(routes: List<Route>, filters: List<(Route) -> Boolean>) =
routes.filter { route -> filters.all { filter -> filter(route) }
您甚至可以在List<T>
上添加扩展功能以提供filterAll
功能,例如:
private fun <T> List<T>.filterAll(filters: List<(T) -> Boolean>) =
filter { item -> filters.all { filter -> filter(item) } }
然后您的视图逻辑就变成:
routers.filterAll(generateFilters())
答案 1 :(得分:0)
如果要保留值,请缓存所有路由,然后对其进行过滤:
val allRoutes = ... // somewhere initialized
val filtered = allRoutes.filter {
it.monthlyPrice != null
}
// use filtered routes, but keep reference to allRoutes
答案 2 :(得分:0)
好吧,这就是我最终要做的..在看到上面@kcoppock的答案之前,我所做的。
我使用了MutableSet来保存我要主动显示给用户的所有路由,并使用以下代码侦听每个框的所有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)
}
请记住,我标记为正确答案(不是这个答案)可能是执行此操作的更好方法。