2013-04-12 2 views
7

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) 

하지만, 그것이 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, IntShort입니다.

  1. 처음에는 Int 대신 구조형을 사용할 수 있다고 생각했습니다. 그러나 그것은 구조적인 유형이 어떤 용도로 사용되기 위해서 스스로를 참조 할 필요가 있음을 의미합니다.
  2. 유용한 것으로 생각되는 Numeric 형질을 들여다 보았습니다. 그것은 모든 숫자 형의 + 메소드를 캡슐화합니다. 그러나, 나는 나의 경우에 그것을 사용하는 방법을 잘 모르겠습니다. 내 함수의 사용자가 강제로 값을 값으로 감싸서 내 함수가 작동하도록하고 싶지 않습니다. 함수 자체는 어떻게 든 그것을 암묵적으로 감싸고 Numeric.plus을 호출해야합니다.

이 문제를 해결하는 방법에 대한 제안이 있습니다. 당신은 숫자 값에만 관심이 있다면

+1

답변이기는하지만 너무 간결하므로 다음과 같이 표시 할 필요가 없습니다. typeclass를 사용하십시오. 다른 사람이 세부 사항을 조만간 알려줄 것입니다. 그렇지 않다면 나는 시간을 벌려고 노력할 것입니다. –

답변

15

, 표준 Numeric 타입 클래스를 사용하여이를 수행 할 수 :

num 암시 적 매개 변수 V가 숫자 타입이라고 증거 역할을하고를 제공
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)} } 
} 

이 유형의 경우 + 작업입니다.