Есть ли лучший способ сделать это:
val totalScore = set.foldLeft(0)( _ + score(_) )
или это:
val totalScore = set.toSeq.map(score(_)).sum
Я думаю, что это - вполне общая операция, так ожидал что-то более гладкое как:
val totalScore = set.sum( score(_) )
Что ж, есть альтернативные способы записать это:
val totalScore = set.toSeq.map(score(_)).sum
val totalScore = set.toSeq.map(score).sum
val totalScore = set.toSeq map score sum
Последний может потребовать точку с запятой в конце, если следующая строка не начинается с ключевого слова. Можно также использовать .view
вместо .toSeq
, что позволит избежать выделения временной коллекции. Однако я не уверен, что текущее поведение .view
(показ повторяющихся элементов) является правильным.
Проще:
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
Seq.sum
не принимает функцию, которую можно было бы использовать для подсчета суммы. Вы могли бы определить неявное преобразование, которое "пимпает" 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.
В качестве альтернативы, перегрузка Seq # sum
, которая принимает неявное преобразование в Numeric
, может использоваться, если тип в коллекции должен быть оценен / суммирован сам по себе не имеет оператора сложения. Однако, поскольку это неявный параметр преобразования, он не будет применяться, если только это не потребуется для проверки типа сокращения закрытия.