Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Collections 使用多个对象字段/多个条件筛选ArrayList_Collections_Filter_Kotlin - Fatal编程技术网

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)
}