Лучший способ забить и сложить в Scala? - PullRequest
9 голосов
/ 21 мая 2010

Есть ли лучший способ сделать это:

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

или это:

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

Я думаю, что это довольно распространенная операция, поэтому ожидал чего-то более гладкого:

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

Ответы [ 4 ]

17 голосов
/ 21 мая 2010

Ну, есть альтернативные способы написать это:

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

Последний может потребовать точку с запятой в конце, если следующая строка не начинается с ключевого слова. Можно также использовать .view вместо .toSeq, что позволит избежать выделения временной коллекции. Однако я не уверен, что текущее поведение .view (при отображении повторяющихся элементов) является правильным.

5 голосов
/ 21 мая 2010

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.

1 голос
/ 21 мая 2010

Альтернативно, перегрузка Seq#sum, которая принимает неявное преобразование в Numeric, могла бы использоваться, если у типа в коллекции, которая должна быть оценена / суммирована, нет самого оператора добавления. Тем не менее, поскольку это неявный параметр преобразования, он не будет применен, если не требуется проверка типа Reduction Closure.

1 голос
/ 21 мая 2010

Simpler:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...