使用多个对象字段/多个条件过滤 ArrayList

A91*_*91G 3 collections filter kotlin

所以我在过滤集合方面遇到了一个有趣的问题,我有一个数据类,如下所示:

data class Route(
    val id: Int,
    val name: String,
    val weeklyPrice: Double?,
    val monthlyPrice: Double?,
    val seasonalPrice: Double?,
)
Run Code Online (Sandbox Code Playgroud)

我在 UI 中显示一个 ArrayList,用户可以根据路线是否具有“每周/每月/季节性”价格来过滤列表,请记住我使用的是复选框而不是单选按钮,以便用户可以过滤使用多个选项。IE。仅每周,或每周和每月等。

我的问题是使用过滤器函数和谓词我一次只能基于一个属性进行过滤,如下所示:

routes.filter {
    it.weeklyPrice != null
}
Run Code Online (Sandbox Code Playgroud)

但有时我实际上会根据另一个条件过滤掉我想保留的值,例如用户不想要每周价格的路线,所以我过滤掉了那些但他想要每月价格的路线,但其中一些已经被过滤了基于他们也有每周价格的事实。

任何帮助将不胜感激,我相信它可以完成我只是没有弄清楚如何,也许问题在于首先如何表示数据?我不知道。

非常感谢提前。

kco*_*ock 6

一种方法是生成过滤器列表,例如List<(Route) -> Boolean>,然后在过滤器列表更改时使您的视图无效。

因此,例如,您有以下内容:

// Use your own logic based on user selection here
private fun generateFilters() = listOf<(Route) -> Boolean>(
    { it.id != 0 },
    { it.weeklyPrice != null }
)
Run Code Online (Sandbox Code Playgroud)

然后,根据这组过滤器生成您的视图,即:

private fun filterRoutes(routes: List<Route>, filters: List<(Route) -> Boolean>) =
    routes.filter { route -> filters.all { filter -> filter(route) } 
Run Code Online (Sandbox Code Playgroud)

您甚至可以添加扩展功能List<T>以提供filterAll功能,例如:

private fun <T> List<T>.filterAll(filters: List<(T) -> Boolean>) =
    filter { item -> filters.all { filter -> filter(item) } }
Run Code Online (Sandbox Code Playgroud)

那么你的视图逻辑就变成了:

routers.filterAll(generateFilters())
Run Code Online (Sandbox Code Playgroud)