10

次のようにコーディングするコードがあります。

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

条件がいくつかの要素で真になり、残りのすべての要素で偽になる場合。

elements残念ながら、私は無限のイテレータであるため、これは機能しません(パフォーマンスを無視しても) 。

理解のために「ブレーク」を使用して、特定の条件が成立したときに要素の生成を停止する方法はありますか?そうでなければ、私の計算の慣用的な方法は何でしょうe2か?

4

5 に答える 5

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

したがって、expicistFunctionをオンデマンドで計算し、あるステップでfalseが発生した場合、不要な作業を行うことはありません。

于 2012-11-28T02:02:46.753 に答える
9
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)
于 2012-11-28T05:44:47.983 に答える
3

takeWhileを使用できます。

elements.takeWhile(condition(expensiveFunction(_)))
于 2012-11-28T01:47:06.410 に答える
0

この解決策を見つけました:

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

より良いもの、誰か?

于 2012-11-28T01:58:54.003 に答える
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
于 2012-11-28T02:30:07.350 に答える