6

次のようなコードがあります。

val strs = List("hello", "andorra", "trab", "world")
def f1(s: String) = !s.startsWith("a")
def f2(s: String) = !s.endsWith("b")

val result = strs.filter(f1).filter(f2)

ここで、f1 と f2 は次のような条件に基づいて適用する必要があります。

val tmp1 = if (cond1) strs.filter(f1) else strs
val out  = if (cond2) tmp1.filter(f2) else tmp1

一時変数を使用せずに、これを行うより良い方法はありますtmp1か?

1 つの方法は、次のような関数のリストに基づいてフィルタリングします。

val fs = List(f1 _,f2 _)
fs.foldLeft(strs)((fn, list) => list.filter(fn))

しかし、その後、条件に基づいて関数のリストを作成する必要があります (したがって、一時的な文字列リスト変数を使用する問題を、一時的な関数リスト変数を使用する問題に移します (または、可変リストを使用する必要があります)。 )。

私はこのようなものを探しています(もちろん、これはコンパイルされません。そうでなければ、質問に対する答えがすでにあります):

val result = 
  strs
    .if(cond1, filter(f1))
    .if(cond2, filter(f2))
4

4 に答える 4

10

暗黙のクラスを使用して、この構文を簡単に使用できます。

  val strs = List("hello", "andorra", "trab", "world")

  def f1(s: String) = !s.startsWith("a")

  def f2(s: String) = !s.endsWith("b")

  val cond1 = true
  val cond2 = true

  implicit class FilterHelper[A](l: List[A]) {
    def ifFilter(cond: Boolean, f: A => Boolean) = {
      if (cond) l.filter(f) else l
    }
  }

  strs
    .ifFilter(cond1, f1)
    .ifFilter(cond2, f2)

res1: List[String] = List(hello, world)

メソッド名として使用ifしたかったのですが、予約語です。

于 2013-07-01T14:20:03.093 に答える
2

次のように、フィルターのブロックに条件を含めるのはかなり簡単です。

val result = strs filter (x => !cond1 || f1(x)) filter (x => !cond2 || f2(x))

条件が満たされた場合、結果はフィルターを適用するか、単に同じリストを返します。

于 2013-07-01T14:55:53.423 に答える