Sam*_*son 5 android predicate filter kotlin
假设我有以下谓词作为 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 }
Run Code Online (Sandbox Code Playgroud)
我只想在满足特定条件时应用谓词。例如,如果应用了性别过滤器,则仅按性别进行过滤。或者我只想在已输入的情况下与搜索查询进行匹配。
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
}
}
Run Code Online (Sandbox Code Playgroud)
以前我已经list.filter{ }在每个条件中完成并应用了必要的谓词,但是,由于我最多可以应用 5 个谓词,因此性能非常糟糕,因为每次.filter()调用它都会迭代列表。
有没有一种方法可以以编程方式迭代 aList<Predicate<T>>并将谓词与.and()or组合起来&&,以便我可以应用过滤器一次?或者如果不是,我如何有条件地组合这些谓词?
我将在此处使用最终的 Java 示例,该示例使用Predicates.stream()andCollectors但它需要 Android API 级别 24(高于我当前的 Android 最低级别)。
适用于 < Android API 24
创建 lambda 列表,并有条件地添加您希望匹配列表项的任何谓词。然后使用Collections.Aggregates.all()方法来确保您正在过滤所有谓词。(相当于pred1.and(pred2).and(etc.)...对列表中的所有项目进行操作。)
如果您有大量的谓词需要过滤,那么性能将得到巨大的节省,因为list.filter()仅调用一次。
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) } }
}
Run Code Online (Sandbox Code Playgroud)
有all扩展函数,并且还有一个有趣的点是any扩展函数。我认为您只需在谓词的过滤块中使用它们即可。这是一个非常简单的示例,其中包含一组愚蠢的谓词:
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]
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7162 次 |
| 最近记录: |