有一个正整数序列,当总和直到该元素小于或等于阈值时,需要从元素的右边分割序列。例如,
val seq = Seq(9,8,7,6,5,4,3,2,1)
阈值为10,结果为
Seq(9,8,7,6,5) and Seq(4,3,2,1)
我在反向后尝试了dropWhile
和scanLeft
,但是,它们是二次的或线性的但很复杂。由于我们的序列可能很长,但通常阈值很小,而右侧的元素很少会满足条件。我想知道是否有更好的线性方法来做到这一点。
答案 0 :(得分:0)
一旦达到阈值,这将立即停止。不幸的是,它使用了回归来。
val seq = Seq(9,8,7,6,5,4,3,2,1)
val threshold = 10
def processList(): (Seq[Int], Int) = {
seq.foldRight((Seq[Int](), 0)) {
case (elem, (acc, total)) =>
if (total + elem <= threshold) {
(elem +: acc, total + elem)
} else {
return (acc, total)
}
}
}
processList()
答案 1 :(得分:0)
使用内置方法看起来没有很好的方法,但你可以自己实现它:
def splitRightCumulative[A, B](xs: Seq[A])(start: B)(f: (B, A) => B, cond: B => Boolean): (Seq[A], Seq[A]) = {
def _loop(current: B, xs: Seq[A], acc: Seq[A]): (Seq[A], Seq[A]) = {
val next = f(current, xs.head)
if (cond(next)) {
_loop(next, xs.tail, xs.head +: acc)
} else {
(xs.reverse, acc)
}
}
_loop(start, xs.reverse, Seq.empty)
}
val xs = List(9, 8, 7, 6, 5, 4, 3, 2, 1)
val (left, right) = splitRightCumulative(xs)(0)(_ + _, _ <= 10)
如果您总是积累与集合中的内容相同的类型,则可能不需要第二个类型参数(B
)。