Rewriting imperative for loop to declarative style in Scala

Viewed 290

How do I rewrite the following loop (pattern) into Scala, either using built-in higher order functions or tail recursion?

This the example of an iteration pattern where you do a computation (comparison, for example) of two list elements, but only if the second one comes after first one in the original input. Note that the +1 step is used here, but in general, it could be +n.

public List<U> mapNext(List<T> list) {
    List<U> results = new ArrayList();

    for (i = 0; i < list.size - 1; i++) {
        for (j = i + 1; j < list.size; j++) {
            results.add(doSomething(list[i], list[j]))
        }
    }

    return results;
}

So far, I've come up with this in Scala:

def mapNext[T, U](list: List[T])(f: (T, T) => U): List[U] = {
  @scala.annotation.tailrec
  def loop(ix: List[T], jx: List[T], res: List[U]): List[U] = (ix, jx) match {
    case (_ :: _ :: is, Nil) => loop(ix, ix.tail, res)
    case (i :: _ :: is, j :: Nil) => loop(ix.tail, Nil, f(i, j) :: res)
    case (i :: _ :: is, j :: js) => loop(ix, js, f(i, j) :: res)
    case _ => res
  }

  loop(list, Nil, Nil).reverse
}

Edit: To all contributors, I only wish I could accept every answer as solution :)

4 Answers
Related