gpt4 book ai didi

android - 有条件地在 Kotlin 中组合 Lambda 以过滤多个谓词

转载 作者:行者123 更新时间:2023-12-04 01:24:28 24 4
gpt4 key购买 nike

假设我有以下谓词作为 Villager POJO 的预定义 lambda。

    val matchesSearch: (Villager, String) -> Boolean =
{ villager: Villager, query: String -> villager.name.contains(query) }

val matchesGender: (Villager, Int) -> Boolean =
{ villager: Villager, filter: Int -> filter == villager.gender }

val matchesPersonality: (Villager, Int) -> Boolean =
{ villager: Villager, filter: Int -> filter == villager.personality }

val matchesSpecies: (Villager, Int) -> Boolean =
{ villager: Villager, filter: Int -> filter == villager.species }

val matchesHobby: (Villager, Int) -> Boolean =
{ villager: Villager, filter: Int -> filter == villager.hobby }

如果满足某个条件,我只想应用谓词。例如,如果已应用性别过滤器,则仅按性别过滤。或者,如果已输入,我只想匹配搜索查询。
fun getVillagersThatMatchQueryAndFilters(list: List<Villager>): List<Villager> {

val conditions = ArrayList<Predicate<Villager>>()

if (searchQuery.isNotEmpty()) {
// TODO: apply the matchesSearch() predicate lambda
conditions.add(Predicate { villager -> villager.name.contains(query) })
}
if (genderFilter > 0) {
// TODO: apply the matchesGender() predicate lambda
conditions.add(Predicate { genderFilter == villager.gender })
}
if (personalityFilter > 0) {
// TODO: apply the matchesPersonality() predicate lambda
conditions.add(Predicate { personalityFilter == villager.personality })
}
if (speciesFilter > 0) {
// TODO: apply the matchesSpecies() predicate lambda
conditions.add(Predicate { speciesFilter == villager.species })
}
if (hobbyFilter > 0) {
// TODO: apply the matchesHobby() predicate lambda
conditions.add(Predicate { hobbyFilter == villager.hobby })
}

return list.filter {
// TODO: match on all conditionally applied predicates
conditions.allPredicatesCombinedWithAnd() // this doesn't actually exist
}
}

以前我做过 list.filter{ }在每个条件中并应用必要的谓词,但是,由于我最多可以应用 5 个谓词,因此性能非常糟糕,因为它每次都会遍历列表 .filter()叫做。

有没有办法以编程方式迭代 List<Predicate<T>>并将谓词与 .and() 结合起来或 &&这样我就可以应用过滤器一次?如果没有,我怎么能 有条件地结合这些谓词?

我将使用最终的 Java 示例 here使用 Predicates.stream()Collectors但它需要 Android API 级别 24(高于我当前的 Android 最低级别)。

下面的解决方案 - 感谢 @Laurence 的建议和 @IR42

适用于 < Android API 24

创建一个 lambda 列表并有条件地添加您希望匹配列表项的任何谓词。然后使用 Collections.Aggregates.all()方法来确保您正在过滤所有谓词。 (相当于对列表中的所有项目执行 pred1.and(pred2).and(etc.)...。)

如果您有大量谓词要过滤为 list.filter(),则可以节省大量性能。仅称为 ONCE。
fun getVillagersThatMatchQueryAndFilters(list: List<Villager>): List<Villager> {

val conditions = ArrayList<(Villager) -> Boolean>()

if (searchQuery.isNotEmpty()) {
conditions.add{ it.name.contains(query) }
}
if (genderFilter > 0) {
conditions.add{ genderFilter == it.gender }
}
if (personalityFilter > 0) {
conditions.add{ personalityFilter == it.personality }
}
if (speciesFilter > 0) {
conditions.add{ speciesFilter == it.species }
}
if (hobbyFilter > 0) {
conditions.add{ hobbyFilter == it.hobby }
}

return list.filter { candidate -> conditions.all { it(candidate) } }
}

最佳答案

all扩展功能,作为兴趣点 any扩展功能也是如此。我认为您只需要在谓词的过滤器 block 中使用它们即可。这是一个非常简单的示例,其中包含一组愚蠢的谓词:

fun main() {
val thingsToFilter = listOf(-1,2,5)

val predicates = listOf(
{ value: Int -> value > 0 },
{ value: Int -> value > 4 }
)

val filtered = thingsToFilter.filter {candidate ->
predicates.all{ it(candidate)}
}

print(filtered) // Outputs [5]

}

关于android - 有条件地在 Kotlin 中组合 Lambda 以过滤多个谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62144643/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com