jsa*_*ata 9 scala break infinite-sequence for-comprehension
我有一段代码,代码如下:
val e2 = for (e <- elements if condition(expensiveFunction(e))) yield {
expensiveFunction(e)
}
Run Code Online (Sandbox Code Playgroud)
条件对于少数元素是正确的,然后对所有剩余的元素变为假.
不幸的是,这不起作用(即使我忽略性能)因为我elements是一个无限的迭代器.
有没有办法在for-comprehension中使用"break",这样当某个条件成立时它会停止产生元素?否则,计算我的scala-idiomatic方法是e2什么?
om-*_*nom 20
你可以采用懒惰的做法:
val e2 = elements.toIterator
.map(expensiveFunction)
.takeWhile(result => result == true) // or just .takeWhile(identity)
// you may want to strict iterator, (e.g. by calling .toList) at the end
Run Code Online (Sandbox Code Playgroud)
因此,您可以按需计算昂贵的功能,如果在某个步骤中存在错误,则不会执行不必要的工作.
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)
Run Code Online (Sandbox Code Playgroud)
编辑,另一个演示:
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)
Run Code Online (Sandbox Code Playgroud)