Scala reduceByKey 函数 - 使用任何具有 + 方法的类型 [英] Scala reduceByKey function - use any type that has + method

查看:39
本文介绍了Scala reduceByKey 函数 - 使用任何具有 + 方法的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个名为 reduceByKey 的简单函数,它接受(键、数字)对的集合并逐键返回缩减的集合.

 def reduceByKey[K](collection: Traversable[Tuple2[K, Int]]) = {收藏.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))标度>reduceByKey(col)res42:scala.collection.immutable.Map[带序列化的产品,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))标度>reduceByKey(col)<console>:13: 错误:类型不匹配;发现:列表[(具有可序列化的产品,双)]要求:可遍历[(?, Int)]reduceByKey(col)^

当然,我可以为不同的类型制定不同的方法,但这很愚蠢.基本上我希望我的方法适用于任何定义了 + 方法的类型.那将是 DoubleFloatLongIntShort.>

  1. 起初,我认为我可以使用结构类型而不是 Int.但这意味着结构类型需要引用自身才能发挥作用.
  2. 我研究了 Numeric 我认为可能有用的特征.它封装了所有数值类型的 + 方法.但是,我不确定如何在我的情况下使用它.我不想强迫我的函数的用户为了我的函数工作而将值包装在 Numeric 中.函数本身应该以某种方式隐式包装它并调用 Numeric.plus.

对于如何解决这个问题,我愿意接受任何建议.

解决方案

如果你只对数值感兴趣,你可以使用标准的 Numeric 类型类并这样做:

def reduceByKey[K,V](collection: Traversable[Tuple2[K, V]])(implicit num: Numeric[V]) = {进口数量._收藏.groupBy(_._1).map { case (group: K, traversable) =>traversable.reduce{(a,b) =>(a._1, a._2 + b._2)} }}

num 隐式参数作为 V 是数字类型的证据,并为该类型提供 + 操作.>

I am writing a simple function called reduceByKey that takes a collection of (key, numeric) pairs and returns reduced collection by key.

  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.

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, Int and Short.

  1. 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.
  2. I looked into Numeric trait 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.

I am open to any suggestions as how to solve this.

解决方案

If you are only interested in numeric values, you can use the standard Numeric type class and do this:

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 implicit parameter serves as an evidence that V is a numeric type, and provides the + operation for this type.

这篇关于Scala reduceByKey 函数 - 使用任何具有 + 方法的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆