如何使用谓词列表过滤集合
How to filter a collection using a list of predicates
我有一个元素列表,例如:
val myList = listOf(1,2,3,4,5,6,7)
列表可以是任何类型,这只是一个例子。
现在我有一个任意长度的谓词列表:
val myPredicates = listOf({myInt: Int -> myInt > 1}, {myInt: Int -> myInt%2 == 0})
如何通过将所有谓词按列表顺序应用到 myList
来过滤列表并在新列表中获得结果?我觉得答案就在使用 reduce
或 fold
运算符的某个地方,但我却找不到答案。
一种方法是首先使用 fold
将所有谓词组合成一个谓词 ((T) -> Boolean
),然后使用内置的 filter
方法应用该谓词。
fun <T> Iterable<T>.filter(predicates: Iterable<(T) -> Boolean>) =
predicates.fold({ true }) { acc: (T) -> Boolean, next ->
{ acc(it) && next(it) }
}.let { this.filter(it) }
fun main() {
val myList = listOf(1,2,3,4,5,6,7)
val myPredicates = listOf({myInt: Int -> myInt > 2}, {myInt: Int -> myInt%2 == 0})
println(myList.filter(myPredicates))
// [4, 6]
}
由于&&
的短路性质和acc(it)
后跟[=16=]的顺序,每个谓词都会按顺序得到运行,如果有的话一个产生 false
,其余的不会得到 运行.
我能想到的最简单的解决方案是在 filter
调用的谓词列表上使用 all,如下所示:
myList.filter { elt -> myPredicates.all { it(elt) } }
当给定元素 elt
的所有谓词都为真时,myPredicates.all { it(elt) }
returns 部分为真。
我有一个元素列表,例如:
val myList = listOf(1,2,3,4,5,6,7)
列表可以是任何类型,这只是一个例子。 现在我有一个任意长度的谓词列表:
val myPredicates = listOf({myInt: Int -> myInt > 1}, {myInt: Int -> myInt%2 == 0})
如何通过将所有谓词按列表顺序应用到 myList
来过滤列表并在新列表中获得结果?我觉得答案就在使用 reduce
或 fold
运算符的某个地方,但我却找不到答案。
一种方法是首先使用 fold
将所有谓词组合成一个谓词 ((T) -> Boolean
),然后使用内置的 filter
方法应用该谓词。
fun <T> Iterable<T>.filter(predicates: Iterable<(T) -> Boolean>) =
predicates.fold({ true }) { acc: (T) -> Boolean, next ->
{ acc(it) && next(it) }
}.let { this.filter(it) }
fun main() {
val myList = listOf(1,2,3,4,5,6,7)
val myPredicates = listOf({myInt: Int -> myInt > 2}, {myInt: Int -> myInt%2 == 0})
println(myList.filter(myPredicates))
// [4, 6]
}
由于&&
的短路性质和acc(it)
后跟[=16=]的顺序,每个谓词都会按顺序得到运行,如果有的话一个产生 false
,其余的不会得到 运行.
我能想到的最简单的解决方案是在 filter
调用的谓词列表上使用 all,如下所示:
myList.filter { elt -> myPredicates.all { it(elt) } }
当给定元素 elt
的所有谓词都为真时,myPredicates.all { it(elt) }
returns 部分为真。