Scala reduceByKey 函数 - 使用任何具有 + 方法的类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15975384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala reduceByKey function - use any type that has + method
提问by Grega Ke?pret
I am writing a simple function called reduceByKeythat takes a collection of (key, numeric) pairs and returns reduced collection by key.
我正在编写一个名为的简单函数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)} }
}
This currently works for:
这目前适用于:
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)
But, I as soon as I want to use non-Int type for numeric, it fails miserably, as it expects an Int.
但是,一旦我想对数字使用非 Int 类型,它就会失败,因为它期望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)
^
Of course, I could make different methods for different types, but that would be silly. Basically I want my method to work with any type that has +method defined. That would be Double, Float, Long, Intand Short.
当然,我可以为不同的类型制定不同的方法,但这很愚蠢。基本上我希望我的方法适用于任何+定义了方法的类型。那将是Double, Float, Long,Int和Short。
- At first, I thought I could use structural type instead of Int. But that would mean the structural type would need to reference itself in order to be of any use.
- I looked into Numerictrait that I think could be useful. It encapsulates the + methods of all numeric types. However, I am not sure how to use it in my case. I dont want force the user of my function to wrap values in Numeric just for my function to work. The function itself should somehow implicitly wrap it up and invoke
Numeric.plus.
- 起初,我认为我可以使用结构类型而不是 Int。但这意味着结构类型需要引用自身才能使用。
- 我研究了我认为可能有用的数字特征。它封装了所有数值类型的+方法。但是,我不确定如何在我的情况下使用它。我不想强迫我的函数的用户为了我的函数工作而将值包装在 Numeric 中。函数本身应该以某种方式隐式包装它并调用
Numeric.plus.
I am open to any suggestions as how to solve this.
我对如何解决这个问题的任何建议持开放态度。
回答by Régis Jean-Gilles
If you are only interested in numeric values, you can use the standard Numerictype class and do this:
如果您只对数值感兴趣,您可以使用标准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)} }
}
The numimplicit parameter serves as an evidence that Vis a numeric type, and provides the +operation for this type.
的num隐式参数用作证据表明V是数字型,并且提供了+操作这种类型。

