Фильтр в ArrayList с помощью нескольких полей объекта / нескольких условий

голоса
1

Так что у меня есть интересная проблема с коллекциями фильтрации, у меня есть класс данных следующим образом:

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

Я отображая ArrayList в пользовательском интерфейсе, и пользователь имеет возможность фильтровать список на основе, имеет ли маршрут «еженедельно / ежемесячно / сезонные» цены, иметь в виду, я использую флажков не радиокнопки, так что пользователь может фильтровать используя несколько вариантов. то есть. только раз в неделю, или как еженедельно и ежемесячно, и так далее.

Моя проблема заключается в том, что с помощью функции фильтра и предикат Я могу только фильтр на основе одного атрибута в то время как так:

routes.filter {
    it.weeklyPrice != null
}

Но иногда я на самом деле отфильтровать значения, которые я хотел, чтобы на основе другого состояния, например, пользователь не хочет, чтобы маршруты с еженедельными цены, так что я отфильтровывать те из, но он хочет, чтобы те, с ежемесячными из них, но некоторые из них были уже отфильтрованы на основании того, что они имели еженедельные цены, а также.

Любая помощь будет оценена, я уверен, что это может быть сделано, я просто не понял, как, может быть, проблема в том, как данные представлены в первую очередь? Я не уверен.

Большое спасибо заранее.

Задан 27/11/2018 в 15:11
источник пользователем
На других языках...                            


3 ответов

голоса
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())
Ответил 27/11/2018 в 17:29
источник пользователем

голоса
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)
}

Имейте в виду, что ответ я помечается как правильно (это не один), вероятно, лучший способ сделать это.

Ответил 28/11/2018 в 15:07
источник пользователем

голоса
0

Если вы хотите сохранить значения, кэш всех маршрутов, а затем фильтровать их:

val allRoutes = ... // somewhere initialized
val filtered = allRoutes.filter {
    it.monthlyPrice != null
}
// use filtered routes, but keep reference to allRoutes
Ответил 27/11/2018 в 15:23
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more