3

次のことを考慮してください。

val stuff = Map[String, Int]("apple" -> 5, "orange" -> 1, "banana" -> 3, "kiwi" -> 2)

val used = 1

val rest = stuff.mapValues{
  case quantity => quantity - used
}.filterNot{
  case (fruit, quantity) => quantity == 0
}

結果は

rest : scala.collection.immutable.Map[String,Int] = Map(apple -> 4, banana -> 2, kiwi -> 1)

私はScalaの専門家ではありませんが、言語が怠惰ではないことを知っています(Haskellとは異なります)。そのmapValuesため、中間体が生成さMapれ、それが入力として渡されますfilterNot(チェーン内に他の操作があった場合)。 。

この役に立たない中間データ構造を回避するにはどうすればよいですか?

注:質問は他のデータ構造に一般化できることを理解しています。ここで使用Mapしているのは、実際のコードで使用していたデータ構造であるためです(ただし、他のデータも使用しています:))

4

3 に答える 3

7

view任意のコレクションクラスのメソッドを使用して、のようなメソッドmapfilter遅延的に適用するコレクションのビューを作成できます。http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library/index.html#scala.collection.TraversableLikeを参照してください

于 2013-01-08T17:15:43.460 に答える
3

これはトリックを行うようです:

object  ChainOpsRS
{
  val stuff = Map[String, Int]("apple" -> 5, "orange" -> 1, "banana" -> 3, "kiwi" -> 2)

  val used = 1

  val rest =
    stuff.collect {
      case (fruit, quantity) if quantity > used => (fruit, quantity - used)
    }

  def main(args: Array[String]) {
    printf("stuff=%s%n", stuff.mkString("{", ", ", "}"))
    printf(" rest=%s%n", rest.mkString("{", ", ", "}"))
  }
}

実行すると、次の出力が生成されます。

stuff={apple -> 5, orange -> 1, banana -> 3, kiwi -> 2}
 rest={apple -> 4, banana -> 2, kiwi -> 1}
于 2013-01-09T15:20:40.340 に答える
3

@Kimの回答に加えて、このmapValuesメソッドは実際には中間結果を計算しないことに注意してください。マップのビューmapValuesを返します。これにより、またはを含む他のほとんどの方法とは異なります。filterNotmap

例:

val rest = stuff.mapValues {
  case quantity =>
    println("reading quantity " + quantity)
    quantity - used
}

rest("apple")
rest("apple")

プリント:

reading quantity 5
reading quantity 5
于 2013-01-08T20:56:49.920 に答える