14

このクラスを検討してください。

 case class Person(val firstName: String, val lastName: String, age: Int)
 val persons = Person("Jane", "Doe", 42) :: Person("John", "Doe", 45) :: 
               Person("Joe", "Doe", 43) :: Person("Doug", "Don", 65) :: 
               Person("Darius", "Don", 24) :: Person("Dora", "Don", 20) :: 
               Person("Dane", "Dons", 29) :: Nil

すべての人の年齢の合計を取得するには、次のようなコードを記述できます。

persons.foldLeft(0)(_ + _.age)

ただし、を使用する場合はsum、最初に値をマップする必要があり、コードは次のようになります。

persons.map(_.age).sum

中間コレクションを作成せずsumにメソッドを使用するにはどうすればよいですか?

(このような「最適化」は、タイトなループで実行されていない場合、おそらく実際のパフォーマンスの違いはないことを知っています。また、レイジービューなどについても知っています。)

次のようなコードを持つことは可能ですか?

persons.sum(_.age)

何をするfoldLeft/reduceLeftする?

4

2 に答える 2

13

あなたが答えたのはあなた自身です。使用するだけviewです:

persons.view.map(_.age).sum

ワークフローを調べて自分を納得させるには:

persons.view.map { p =>
  println("invoking age")
  p.age
}.map { x =>
  println("modifing age")
  x + 0
}.sum

対:

persons.map { p =>
  println("invoking age")
  p.age
}.map { x =>
  println("modifing age")
  x + 0
}.sum
于 2011-02-21T11:13:36.123 に答える
11

ライブラリ内のメソッドsumはこのようには機能しませんが、次のような独自のメソッドを作成できます。

def mySum[T, Res](f: T => Res, seq: TraversableOnce[T])(implicit num: Numeric[Res]) = 
  seq.foldLeft(num.zero)((acc, b) => num.plus(acc, f(b)))

seq.sum(f)暗黙の変換を追加して、代わりに次のように呼び出すこともできます(競合を避けるためにmySum(f, seq)別の名前が必要になる場合があります)。sum

case class SumTraversableOnce[T](val seq: TraversableOnce[T]) { 
  def sum[Res](f: T => Res)(implicit num: Numeric[Res]) = mySum(f, seq)(num) 
}

implicit def toSumTraversableOnce[T](seq: TraversableOnce[T]) = 
  SumTraversableOnce(seq)

または、Scala 2.10以降、

implicit class SumTraversableOnce[T](val seq: TraversableOnce[T]) { 
  def sum[Res](f: T => Res)(implicit num: Numeric[Res]) = mySum(f, seq)(num) 
}
于 2011-02-21T10:52:59.987 に答える