elm
elm

Reputation: 20405

Scala functional code for iteration with a value forwarded to next iteration

How to make this code more functional, where a value from the current iteration is preserved into the next (variable last),

def f(i: Int): Int = ???

var last = -1

for (v <- xs) yield {
  val start = f(v)
  val end = f(start)

  val res = if (last == start - 2) "abc" else "xyz"

  last = end
  res
}

Upvotes: 1

Views: 165

Answers (2)

elm
elm

Reputation: 20405

Noticed this approach with scanLeft (inspired in @mohit approach using foldLeft), here on a pre-processed collection of pairs for start and end, namely for instance

val a = Array((1,2), (3,4), (5,6))

Then in what follows, assume s stands for start and e for end, and so

a.scanLeft((-1,-1,-1)) { case(acc, (s,e)) => (s,e,acc._2) }.drop(1)

which produces triplets with start, end and last,

Array((1,2,-1), (3,4,2), (5,6,4))

over which we can apply the if-else expression; altogether,

a.scanLeft((-1,-1,-1)) { case(acc, (s,e)) => (s,e,acc._2) }.
  drop(1).
  map(t => if (t._3 == t._1 - 2) "abc" else "xyz")

Upvotes: 0

mohit
mohit

Reputation: 4999

I think foldLeft should work. You can pass the value that you will need in the next iteration and the result in a tuple

   val list = (1 to 10 by 2)                       
   //> list  : scala.collection.immutable.Range = Range(1, 3, 5, 7, 9)
   val last = -1
   list.foldLeft((last, List[String]())) {
     case (r, c) => println(s"Current - $c last - ${r._1}")
     (c, r._2 :+ if (...) "abc" else "xyz")
     // c will be the value that you need to pass to the next iteration
     // r._2 will contain the list which you would have got with your for comprehension 
   }
  //> Current - 1 last - -1
  //| Current - 3 last - 1
  //| Current - 5 last - 3
  //| Current - 7 last - 5
  //| Current - 9 last - 7

Upvotes: 3

Related Questions