Scala reduceByKey 函数 - 使用任何具有 + 方法的类型

2024-03-16

我正在编写一个简单的函数,名为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)

但是,一旦我想使用非 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)
                                ^

当然,我可以为不同的类型制定不同的方法,但那会很愚蠢。基本上我希望我的方法适用于任何类型+方法定义。那将是Double, Float, Long, Int and Short.

  1. 起初,我以为可以使用结构类型来代替 Int。但这意味着结构类型需要引用自身才能发挥作用。
  2. 我调查了Numeric http://www.scala-lang.org/api/2.9.2/scala/math/Numeric.html我认为可能有用的特征。它封装了所有数值类型的+方法。但是,我不确定如何在我的情况下使用它。我不想强迫我的函数的用户将值包装在数字中,只是为了我的函数能够工作。函数本身应该以某种方式隐式地包装它并调用Numeric.plus.

我愿意接受任何关于如何解决这个问题的建议。


如果您只对数值感兴趣,可以使用标准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 num隐式参数作为证据V是数字类型,并提供+对于这种类型的操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala reduceByKey 函数 - 使用任何具有 + 方法的类型 的相关文章

随机推荐