Reputation: 354
I am new to scala language and was trying to implement the median function which should work for Int and Long both, this is what I tried to do:
def getMedian[T: Numeric](seq: Seq[T]): T = {
val sortedSeq = seq.sortWith(_ < _)
if (seq.size % 2 == 1) sortedSeq(sortedSeq.size / 2) else {
val (up, down) = sortedSeq.splitAt(seq.size / 2)
(up.last + down.head) / 2
}
}
but the comparison operator is not valid for numeric class. What can I do to accomplish this.
Upvotes: 3
Views: 1346
Reputation: 44918
There is a problem with the result type. If you divide an integer by 2, the result is not necessarily an integer. But who decides about the precision of the result? Should it be Double
? Or would Float
be close enough?
Here is a solution where you have to specify the result type explicitly:
def getMedian[T: Ordering, F]
(seq: Seq[T])
(implicit conv: T => F, f: Fractional[F]): F = {
val sortedSeq = seq.sorted
if (seq.size % 2 == 1) sortedSeq(sortedSeq.size / 2) else {
val (up, down) = sortedSeq.splitAt(seq.size / 2)
import f._
(conv(up.last) + conv(down.head)) / fromInt(2)
}
}
You now can use it as follows:
println(getMedian[Int, Float](List(1,2,3,4)))
println(getMedian[Int, Double](List(1,2,3,4)))
It outputs 2.5 two times, but the first one is single precision, whereas the last one is computed with double precision.
While you're at it, you could implement an O(n) selection algorithm like for example quickselect, and use T: Ordering
for comparing elements. Neither of those algorithms relies on any arithmetic operations.
Upvotes: 5