3

ループ内に高価な計算があり、計算によって生成された最大値を見つける必要がありますが、たとえば、それが LIMIT に等しい場合は、計算を停止してアキュムレータを返したいと思います。

再帰によって簡単に実行できます。

val list: List[Int] = ???
val UpperBound = ???

def findMax(ls: List[Int], max: Int): Int = ls match {
  case h :: rest =>
    val v = expensiveComputation(h)
    if (v == UpperBound) v
    else findMax(rest, math.max(max, v))

  case _ => max
}

findMax(list, 0)

私の質問: この動作テンプレートに名前があり、scala コレクション ライブラリに反映されているかどうか?

更新: Scala で N 回まで、または条件が満たされるまで何かを行う- 興味深いアイデアがあります (遅延と検索または存在を最後に使用する) が、それは私の特定のケースに直接適用できないか、アキュムレータを追跡するために可変変数が必要です。

4

1 に答える 1

4

あなたの再帰関数は非常に優れていると思うので、正直なところそれを変更するつもりはありませんが、コレクションライブラリを使用する方法は次のとおりです。

list.foldLeft(0) {
  case (max, next) =>
    if(max == UpperBound)
      max
    else
      math.max(expensiveComputation(next), max)
}

リスト全体を反復処理しますが、上限に達すると、コストのかかる計算は実行されません。

アップデート

あなたのコメントに基づいて、LinearSeqOptimizedfoldLeft の実装に基づいて、foldLeft を少し調整してみました。

def foldLeftWithExit[A, B](list: Seq[A])(z: B)(exit: B => Boolean)(f: (B, A) => B): B = {
  var acc = z
  var remaining = list
  while (!remaining.isEmpty && !exit(acc)) {
    acc = f(acc, list.head)
    remaining = remaining.tail
  }
  acc
}

それを呼び出す:

foldLeftWithExit(list)(0)(UpperBound==){
  case (max, next) =>  math.max(expensiveComputation(next), max)
}

潜在的に暗黙を使用して、 の最初のパラメーターを省略できますlist。お役に立てれば。

于 2013-11-12T19:56:54.580 に答える