Filtrer une liste de tableaux en utilisant de multiples champs d'objet / plusieurs conditions

voix
1

J'ai donc un problème intéressant avec des collections de filtrage, j'ai une classe de données comme suit:

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

Je l'affichage d'une liste de tableaux dans l'interface utilisateur et l'utilisateur a la possibilité de filtrer la liste en fonction si la route a des prix « par semaine / mois / saison », garder à l'esprit que je utilise des cases à cocher pas de boutons radio afin que l'utilisateur peut filtrer en utilisant plusieurs options. c'est à dire. uniquement à la semaine, ou à la fois hebdomadaire et mensuelle et ainsi de suite.

Mon problème est que l'utilisation de la fonction de filtre et un prédicat je ne peux filtrer à partir d'un attribut à la fois comme ceci:

routes.filter {
    it.weeklyPrice != null
}

Mais parfois, je fait filtrer les valeurs que je voulais garder basé sur une autre condition, par exemple, un utilisateur ne veut pas les routes avec des prix hebdomadaires, donc je filtrer les sortir, mais il veut les avec les mois, mais certains d'entre eux ont déjà été filtré en se basant sur le fait qu'ils avaient des prix hebdomadaires aussi bien.

Toute aide serait appréciée, je suis sûr que cela peut être fait que je viens pas compris comment, peut-être le problème est dans la façon dont les données sont représentées en premier lieu? Je ne suis pas sûr.

Une grande partie grâce à l'avance.

Créé 27/11/2018 à 15:11
source utilisateur
Dans d'autres langues...                            


3 réponses

voix
1

Une approche serait de générer une liste de filtres, par exemple List<(Route) -> Boolean>, puis invalider juste votre point de vue chaque fois que la liste des filtres changent.

Ainsi, par exemple, vous avez quelque chose comme:

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

Ensuite, votre point de vue est généré en fonction de cet ensemble de filtre, à savoir:

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

Vous pouvez même ajouter une fonction d'extension sur List<T>de fournir une filterAllfonctionnalité, quelque chose comme:

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

Ensuite, votre logique de vue devient tout simplement:

routers.filterAll(generateFilters())
Créé 27/11/2018 à 17:29
source utilisateur

voix
0

Ok, voici ce que je fini par faire .. que je l'ai fait avant de voir la réponse de @ kcoppock ci-dessus.

J'ai utilisé un MutableSet pour tenir tous les itinéraires que je veux activement montrer à l'utilisateur et utilisé le code suivant pour écouter tous les événements CheckedChanged pour chaque boîte:

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

Gardez à l'esprit, la réponse que je marqué comme correct (pas celui-ci) est probablement la meilleure façon de le faire.

Créé 28/11/2018 à 15:07
source utilisateur

voix
0

Si vous voulez conserver les valeurs, cache toutes les routes et les filtrer:

val allRoutes = ... // somewhere initialized
val filtered = allRoutes.filter {
    it.monthlyPrice != null
}
// use filtered routes, but keep reference to allRoutes
Créé 27/11/2018 à 15:23
source utilisateur

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