How to cut for understanding short (to break out of it) in scala?

I have a piece of code that will look like this:

val e2 = for (e <- elements if condition(expensiveFunction(e))) yield { expensiveFunction(e) } 

If the condition is true for several elements, then it becomes false for everyone else.

Unfortunately, this does not work (even if I ignore the performance), because my elements is an infinite iterator.

Is there a way to use the “gap” for understanding so that it is not inferior to the elements when a certain condition is met? Otherwise, what would be the scala idiomatic way of calculating my e2 ?

+7
source share
5 answers
 scala> def compute(i: Int) = { println(s"f$i"); 10*i } compute: (i: Int)Int scala> for (x <- Stream range (0, 20)) yield compute(x) f0 res0: scala.collection.immutable.Stream[Int] = Stream(0, ?) scala> res0 takeWhile (_ < 100) res1: scala.collection.immutable.Stream[Int] = Stream(0, ?) scala> res1.toList f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 res2: List[Int] = List(0, 10, 20, 30, 40, 50, 60, 70, 80, 90) 

Edit, another demo:

 scala> def compute(i: Int) = { println(s"f$i"); 10*i } compute: (i: Int)Int scala> for (x <- Stream range (0, 20)) yield compute(x) f0 res0: scala.collection.immutable.Stream[Int] = Stream(0, ?) scala> res0 takeWhile (_ < 100) res1: scala.collection.immutable.Stream[Int] = Stream(0, ?) scala> res1.toList f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 res2: List[Int] = List(0, 10, 20, 30, 40, 50, 60, 70, 80, 90) scala> Stream.range(0,20).map(compute).toList f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 f19 res3: List[Int] = List(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190) scala> Stream.range(0,20).map(compute).takeWhile(_ < 100).toList f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 res4: List[Int] = List(0, 10, 20, 30, 40, 50, 60, 70, 80, 90) 
+8
source

You can go the lazy way:

 val e2 = elements.toIterator .map(expensiveFunction) .takeWhile(result => result == true) // or just .takeWhile(identity) // you may want to strict iterator, (eg by calling .toList) at the end 

So, you compute an expensive function on demand, and if at some stage there is a lie, you will not do unnecessary work.

+17
source

You can simply use takeWhile:

 elements.takeWhile(condition(expensiveFunction(_))) 
+3
source

Found this solution:

 (for (e <- elements) yield { val x= expensiveFunction(e) if (condition(x)) Some(x) else None }).takeWhile(_.nonEmpty).map(_.get) 

Best anyone?

0
source

Here is my idea: If the elements are already a lazy container (e.g. Stream, Iterator):

 (for (e <- elements; buf = expensiveFunction(e); if condition(buf)) yield buf).headOption 

Or no:

 (for (e <- elements.view; buf = expensiveFunction(e); if condition(buf)) yield buf).headOption 
0
source

All Articles