2013-04-12 24 views
7

Tôi đang viết một hàm đơn giản có tên là reduceByKey, cần thu thập các cặp (khóa, số) và trả về bộ sưu tập đã giảm theo khóa.Hàm Scala reduceByKey - sử dụng bất kỳ loại nào có + phương pháp

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)} } 
    } 

này hiện làm việc cho:

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) 

Nhưng, tôi ngay sau khi tôi muốn sử dụng phi Int kiểu cho số, nó thất bại thảm hại, vì nó hy vọng một 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) 
           ^

Tất nhiên, tôi có thể tạo các phương pháp khác nhau cho các loại khác nhau, nhưng điều đó thật ngớ ngẩn. Về cơ bản tôi muốn phương pháp của tôi để làm việc với bất kỳ loại có phương pháp + được xác định. Đó sẽ là Double, Float, Long, IntShort.

  1. Lúc đầu, tôi nghĩ tôi có thể sử dụng loại kết cấu thay vì Int. Nhưng điều đó có nghĩa là loại cấu trúc sẽ cần phải tham chiếu chính nó để có thể sử dụng.
  2. Tôi đã xem xét Numeric đặc điểm mà tôi cho rằng có thể hữu ích. Nó đóng gói các phương thức + của tất cả các kiểu số. Tuy nhiên, tôi không chắc chắn làm thế nào để sử dụng nó trong trường hợp của tôi. Tôi không muốn ép buộc người sử dụng chức năng của tôi để bọc các giá trị trong Numeric chỉ cho chức năng của tôi để làm việc. Bản thân hàm sẽ bằng cách nào đó bọc nó một cách hoàn toàn và gọi Numeric.plus.

Tôi mở cho bất kỳ đề xuất nào về cách giải quyết vấn đề này.

+1

Đó là câu trả lời, nhưng thật đáng sợ khi không xứng đáng được đưa ra như vậy: Sử dụng một kiểu chữ. Một người khác sẽ cung cấp cho các chi tiết đủ sớm, có lẽ. Nếu không, tôi sẽ cố gắng dành thời gian. –

Trả lời

15

Nếu bạn chỉ quan tâm đến giá trị số, bạn có thể sử dụng lớp Numeric loại tiêu chuẩn và thực hiện điều này:

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)} } 
} 

Các tham số ngầm num đóng vai trò như một bằng chứng cho thấy V là một loại số, và cung cấp Hoạt động + cho loại này.

Các vấn đề liên quan