当累积结果满足条件时,Scala 从右边拆分 Int 的序列



有一个正整数序列,当总和到该元素小于或等于阈值时,需要从元素右侧拆分序列。例如

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,但是,它们要么是二次的,要么是线性的,但很复杂。由于我们的序列可能很长,但通常阈值很小,右侧的元素很少符合条件。我想知道是否有更好和线性的方法可以做到这一点。

一旦达到阈值,此操作将停止。不幸的是,它使用返回来中断。

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()

看起来没有使用内置方法执行此操作的好方法,但您可以自己实现它:

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( 可能不是必需的,如果您总是累积与集合中相同的类型。

最新更新