我有一段代码,代码如下:
val e2 = for (e <- elements if condition(expensiveFunction(e))) yield {
expensiveFunction(e)
}
如果某些元素的条件为真,那么对于所有剩余的元素则为假。
不幸的是,这不起作用(即使我忽略了性能),因为我的elements
是一个无限的迭代器。
有没有办法在for-comprehension中使用“break”,所以当某个条件成立时它会停止产生元素?否则,计算我的e2
?
答案 0 :(得分: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
所以你按需计算昂贵的功能,如果某些步骤有假,你就不会做不必要的工作。
答案 1 :(得分:8)
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> 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)
答案 2 :(得分:3)
你可以使用takeWhile:
elements.takeWhile(condition(expensiveFunction(_)))
答案 3 :(得分:0)
找到了这个解决方案:
(for (e <- elements) yield {
val x= expensiveFunction(e)
if (condition(x)) Some(x) else None
}).takeWhile(_.nonEmpty).map(_.get)
一个更好的人,有人吗?
答案 4 :(得分:0)
这是我的想法: 如果元素已经是一个惰性容器(如Stream,Iterator):
(for (e <- elements;
buf = expensiveFunction(e);
if condition(buf)) yield buf).headOption
或不:
(for (e <- elements.view;
buf = expensiveFunction(e);
if condition(buf)) yield buf).headOption