如何使用谓词列表过滤集合

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 来过滤列表并在新列表中获得结果?我觉得答案就在使用 reducefold 运算符的某个地方,但我却找不到答案。

一种方法是首先使用 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 部分为真。