在Scala得分和总和的最佳方式?

时间:2010-05-21 04:24:49

标签: scala sum

有没有更好的方法:

val totalScore = set.foldLeft(0)( _ + score(_) )

或者这个:

val totalScore = set.toSeq.map(score(_)).sum

我认为这是一种非常常见的操作,所以期待更像时尚的东西:

val totalScore = set.sum( score(_) )

4 个答案:

答案 0 :(得分:17)

嗯,还有其他方法可以写它:

val totalScore = set.toSeq.map(score(_)).sum
val totalScore = set.toSeq.map(score).sum
val totalScore = set.toSeq map score sum

如果下一行不以关键字开头,则最后一行可能需要在结尾处使用分号。也可以使用.view代替.toSeq,这样可以避免分配临时集合。但是,我不确定.view的当前行为(显示重复元素)是否正确。

答案 1 :(得分:5)

Seq.sum没有采用可用于对总和进行评分的函数。您可以定义“pimps”Traversable

的隐式转换
implicit def traversableWithSum[A](t: Traversable[A])(implicit m: Numeric[A]) = new {
  def sumWith(f: A => A) = t.foldLeft(m.zero)((a, b) => m.plus(a, f(b)))
}

def score(i: Int) = i + 1

val s = Set(1, 2, 3)

val totalScore = s.sumWith(score _)
println(totalScore)
=> 9

请注意,Numeric特征仅存在于Scala 2.8中。

答案 2 :(得分:1)

简单:

scala> val is1 = Set(1, 4, 9, 16)
is1: scala.collection.immutable.Set[Int] = Set(1, 4, 9, 16)
scala> is1.reduceLeft(_ + _)
res0: Int = 30

使用您的分数方法:

scoreSet.reduceLeft(_ + score(_))

警告,但是失败的是减少的集合是空的而折叠不是:

scala> val is0 = Set[Int]()
is0: scala.collection.immutable.Set[Int] = Set()

scala> is0.foldLeft(0)(_ + _)
res1: Int = 0

答案 3 :(得分:1)

或者,如果要评分/求和的集合中的类型本身没有加法运算符,则可以使用隐式转换为Seq#sum的{​​{1}}重载。但是,因为它是一个隐式转换参数,所以除非需要进行reduce闭包类型检查,否则不会应用它。