関数 List(MyClass => Boolean) のリストとして表現されるフィルターがいくつかあります。すべてのメンバーの論理積 (AND) を取得しようとしています。ここで折り畳みを使用できる気がしますが、特に MyClass 引数を関数に渡す方法に関する構文がわかりません。
5 に答える
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
2 番目のフィルターが失敗するため、最後のフィルター (副作用があります) は適用されません。
それはとても簡単です。List(MyClass => Boolean)
関数の名前がpredicates and
MyClass you are testing is named
myClass`であると仮定します。
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)
}
説明: 述語のリストが次の 3 つの関数で構成されている場合foo(myClass: MyClass): Boolean
、上記のコードは次bar(myClass: MyClass): Boolean
とbuzz(myClass: MyClass): Boolean
ほぼ同等です。
((true && foo(myClass)) && bar(myClass) && buzz(myClass)
このような の使用例foldLeft
について、少し前に記事を書きました。
では、そのような述語を 2 つ考えてみましょう。
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)
}
predicates.foldLeft( true ) ( _ && _( myClass ) )
また動作する可能性があります。
これらのケースで私が行ったことは、「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(_&&_)