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

The method sum in the library doesn't work this way, but you could write your own which does:

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)))

You could also add an implicit conversion so you can call it like seq.sum(f) instead of mySum(f, seq) (you may need a different name than sum to avoid conflicts):

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)

or, since 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 回答