Reputation: 20405
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
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
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