首页 > 解决方案 > 使用多个对象字段/多个条件过滤 ArrayList

问题描述

所以我有一个过滤集合的有趣问题,我有一个数据类如下:

data class Route(
    val id: Int,
    val name: String,
    val weeklyPrice: Double?,
    val monthlyPrice: Double?,
    val seasonalPrice: Double?,
)

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

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

routes.filter {
    it.weeklyPrice != null
}

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

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

非常感谢提前。

标签: collectionsfilterkotlin

解决方案


一种方法是生成过滤器列表,例如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())

推荐阅读