IntHistogram counts words and displays them count-descending:
object IntHistogram {
def main(args: Array[String]) {
val wordsToCount = "foo foo bar foo bar wtf foo bar".split(" ")
val histogram = new IntHistogram
for (word <- wordsToCount) histogram(word) += 1
println(histogram)
/*
(foo,4)
(bar,3)
(wtf,1)
*/
}
}
class IntHistogram extends collection.mutable.HashMap[String,Int] {
override def default(key:String) = 0
def descendingPairs = toList.sortBy(_._2).reverse
override def toString() = descendingPairs.mkString("\n")
}
I needed a DoubleHistogram, and I resorted to copy-and-paste because I couldn’t figure out how to define a generic “Histogram[NumberSuperClassOfIntAndDouble]” trait:
class DoubleHistogram extends collection.mutable.HashMap[String,Double] {
override def default(key:String) = 0
def descendingPairs = toList.sortBy(_._2).reverse
override def toString() = descendingPairs.mkString("\n")
}
Can a smart/knowledgeable person show me how to define such a supertrait, so I can avoid the ugly copy-and-paste boilerplate?
Thanks in advance,
PT
P.S. I really want Histogram to be a trait, so I can mix the Histogram behavior into any numerically-valued Map. In reality there are lots of behaviors I need, besides a descending toString method; I simplified it for this question. Here Num is the fictional numeric superclass of Int and Double:
trait Histogram[Num] extends collection.Map[String,Num] {
override def default(key:String) = 0
def descendingPairs = toList.sortBy(_._2).reverse
override def toString() = descendingPairs.mkString("\n")
}
I tried using Numeric, Number, import Ordering.Implicits._, all kinds of stuff… to no avail.
This seems to work just fine with
Numeric. Not that you can’t makeHistograma trait because of the context bound onN, butIntHistogramandDoubleHistogramcan be traits.If you really, really need Histogram to be a trait, you can do it this way:
But then you have to instantiate it like this in main: