Функция Scala reduceByKey-используйте любой тип, который имеет метод +
я пишу простую функцию под названием reduceByKey
который принимает коллекцию (ключевых, числовых) пар и возвращает уменьшенную коллекцию по ключу.
def reduceByKey[K](collection: Traversable[Tuple2[K, Int]]) = {
collection
.groupBy(_._1)
.map { case (group: K, traversable) => traversable.reduce{(a,b) => (a._1, a._2 + b._2)} }
}
в настоящее время работает на:
scala> val col = List((("some","key"),100), (("some","key"),100), (("some","other","key"),50))
col: List[(Product with Serializable, Int)] = List(((some,key),100), ((some,key),100), ((some,other,key),50))
scala> reduceByKey(col)
res42: scala.collection.immutable.Map[Product with Serializable,Int] = Map((some,key) -> 200, (some,other,key) -> 50)
но, как только я хочу использовать тип non-Int для numeric, он терпит неудачу, так как он ожидает Int
.
scala> val col = List((("some","key"),100.toDouble), (("some","key"),100.toDouble), (("some","other","key"),50.toDouble))
col: List[(Product with Serializable, Double)] = List(((some,key),100.0), ((some,key),100.0), ((some,other,key),50.0))
scala> reduceByKey(col)
<console>:13: error: type mismatch;
found : List[(Product with Serializable, Double)]
required: Traversable[(?, Int)]
reduceByKey(col)
^
конечно, я мог делать разные методы для разных типов, но это было бы глупо. В основном я хочу, чтобы мой метод работы с любой типа +
способ определенными. Это было бы Double
, Float
, Long
, Int
и Short
.
- сначала я думал, что могу использовать структурный тип вместо Int. Но это означало бы, что структурный тип должен ссылаться на себя, чтобы быть полезным.
- я заглянул в цифровой черта, которая, я думаю, может быть полезной. Он инкапсулирует методы + всех числовых типов. Однако, я не уверен, как использовать его в моем случае. Я не хочу заставлять пользователя моей функции обертывать значения в числовые только для работы моей функции. Сама функция должна каким-то образом неявно обернуть ее и вызвать
Numeric.plus
.
я открыт для любых предложений, как решить эту.
1 ответов
если вас интересуют только числовые значения, вы можете использовать стандартный Numeric
введите класс и сделайте следующее:
def reduceByKey[K,V](collection: Traversable[Tuple2[K, V]])(implicit num: Numeric[V]) = {
import num._
collection
.groupBy(_._1)
.map { case (group: K, traversable) => traversable.reduce{(a,b) => (a._1, a._2 + b._2)} }
}
на num
неявный параметр служит доказательством того, что V
является числовым типом и предоставляет +
операция для этого типа.