当累积结果满足条件时,Scala从右侧分裂Seq

时间:2017-07-17 18:08:19

标签: scala scala-collections

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

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)

我在反向后尝试了dropWhilescanLeft,但是,它们是二次的或线性的但很复杂。由于我们的序列可能很长,但通常阈值很小,而右侧的元素很少会满足条件。我想知道是否有更好的线性方法来做到这一点。

2 个答案:

答案 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)。