当某些条件为真时,Scala foldLeft [英] Scala foldLeft while some conditions are true
问题描述
如何在Scala中模拟以下行为?也就是说,在满足蓄能器上的某些特定条件时,请保持折叠状态.
How to emulate following behavior in Scala? i.e. keep folding while some certain conditions on the accumulator are met.
def foldLeftWhile[B](z: B, p: B => Boolean)(op: (B, A) => B): B
例如
scala> val seq = Seq(1, 2, 3, 4)
seq: Seq[Int] = List(1, 2, 3, 4)
scala> seq.foldLeftWhile(0, _ < 3) { (acc, e) => acc + e }
res0: Int = 1
scala> seq.foldLeftWhile(0, _ < 7) { (acc, e) => acc + e }
res1: Int = 6
更新:
基于@Dima的答案,我意识到我的意图有些副作用.所以我使它与 takeWhile
同步,即,如果谓词不匹配,则不会前进.并添加更多示例以使其更清晰.(注意:不适用于 Iterator
s)
Based on @Dima answer, I realized that my intention was a little bit side-effectful. So I made it synchronized with takeWhile
, i.e. there would be no advancement if the predicate does not match. And add some more examples to make it clearer. (Note: that will not work with Iterator
s)
推荐答案
首先,请注意您的示例似乎是错误的.如果我正确理解您的描述,结果应该是 1
(满足谓词 _< 3
的最后一个值),而不是 6 代码>
First, note that your example seems wrong. If I understand correctly what you describe, the result should be 1
(the last value on which the predicate _ < 3
was satisfied), not 6
最简单的方法是使用 return
语句,该语句在scala中非常皱眉,但是我想,出于完整性考虑,我会提到它.
The simplest way to do this is using a return
statement, which is very frowned upon in scala, but I thought, I'd mention it for the sake of completeness.
def foldLeftWhile[A, B](seq: Seq[A], z: B, p: B => Boolean)(op: (B, A) => B): B = foldLeft(z) { case (b, a) =>
val result = op(b, a)
if(!p(result)) return b
result
}
由于我们要避免使用return,因此有可能使用 scanLeft
:
Since we want to avoid using return, scanLeft
might be a possibility:
seq.toStream.scanLeft(z)(op).takeWhile(p).last
这有点浪费,因为它会累积所有(匹配的)结果.您可以使用 iterator
而不是 toStream
来避免这种情况,但是出于某些原因, Iterator
没有 .last
,因此,您必须明确地额外扫描一次:
This is a little wasteful, because it accumulates all (matching) results.
You could use iterator
instead of toStream
to avoid that, but Iterator
does not have .last
for some reason, so, you'd have to scan through it an extra time explicitly:
seq.iterator.scanLeft(z)(op).takeWhile(p).foldLeft(z) { case (_, b) => b }
这篇关于当某些条件为真时,Scala foldLeft的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!