4

我有一些过滤器表示为函数 List(MyClass => Boolean) 的列表。我试图获得所有成员的逻辑连接(AND)。我有一种感觉,我可以在这里使用折叠。但我没有得到语法,尤其是关于如何将 MyClass 参数传递给函数的语法。

4

5 回答 5

3

您可以foldLeft在这里使用,但forall要好得多:

def check[A](filters: Seq[A => Boolean])(a: A) = filters.forall(_(a))

其工作原理如下:

scala> val filters = Seq[Int => Boolean]((_ > 0), (_ % 2 == 1), (_ < 1000))
filters: Seq[Int => Boolean] = List(<function1>, <function1>, <function1>)

scala> check(filters)(10)
res0: Boolean = false

scala> check(filters)(103)
res1: Boolean = true

它还有一个懒惰的额外优势:

scala> check(filters :+ { i: Int => print(i); true })(10)
res2: Boolean = false

最后一个过滤器(有副作用)没有应用,因为第二个过滤器失败了。

于 2012-06-12T18:26:32.510 回答
2

这很简单。假设您List(MyClass => Boolean)的函数名为predicates andMyClass you are testing is namedmyClass`:

val result: Boolean = predicates.foldLeft(true) {
  (value, predicate) => 
    value && predicate(myClass)
}

或者在包装函数中:

def conjunction(myClass: MyClass, predicates: List[MyClass => Boolean]) = 
  predicates.foldLeft(true) {
    (value, predicate) => 
      value && predicate(myClass)
  }

解释:如果你的谓词列表由三个函数组成:foo(myClass: MyClass): Boolean,上面bar(myClass: MyClass): Booleanbuzz(myClass: MyClass): Boolean代码大致相当于:

((true && foo(myClass)) && bar(myClass) && buzz(myClass)

不久前我写了一篇关于foldLeft.

于 2012-06-12T18:18:51.450 回答
1

好吧,让我们考虑两个这样的谓词:

val pa: T => Boolean = ???
val pb: T => Boolean = ???

它们的结合将是这样的:

val pab: T => Boolean = (v: T) => pa(V) && pb(v)

从那里你有折叠的公式:

list.tail.foldLeft(list.head) {
  case (pa, pb) => v => pa(v) && pb(v)
}
于 2012-06-12T18:36:36.190 回答
0

predicates.foldLeft( true ) ( _ && _( myClass ) )也可能工作。

于 2012-06-12T18:24:57.363 回答
0

在这些情况下,我所做的是使用“Pimp-My-Library”模式在谓词上添加布尔运算,这只是对结果的布尔运算,提升到谓词上的明显布尔组合器。因此我可以说类似

import MyRichPredicate;

val f:Int=>Boolean = (x:Int)=>x%3==0
val g:Int=>Boolean = (x:Int)=>x%5==0
val h = f && !g  //equivalent to (x:Int)=> x%3 == 0 && x%5!=0
print(h(9)) // prints true
print(h(15)) // prints false

鉴于那种管道,你想要的折叠可以写成

predicates.foldLeft(x=>true)(_&&_)

甚至更性感

predicates.reduce(_&&_)
于 2012-06-12T20:07:05.623 回答