I’m afraid this is another noob question.
What I want to do is to use a Map
in order to count how often a word appears in a poe…m and then print the results to the console.
I went to the following code which I believe is working (while probably not quite idiomatic):
val poe_m="""Once upon a midnight dreary, while I pondered weak and weary,
|Over many a quaint and curious volume of forgotten lore,
|While I nodded, nearly napping, suddenly there came a tapping,
|As of some one gently rapping, rapping at my chamber door.
|`'Tis some visitor,' I muttered, `tapping at my chamber door -
|Only this, and nothing more.'"""
val separators=Array(' ',',','.','-','\n','\'','`')
var words=new collection.immutable.HashMap[String,Int]
for(word<-poe_m.stripMargin.split(separators) if(!word.isEmpty))
words=words+(word.toLowerCase -> (words.getOrElse(word.toLowerCase,0)+1))
words.foreach(entry=>println("Word : "+entry._1+" count : "+entry._2))
As far as I understand, in Scala, immutable data structures are preferred to mutable ones and val
preferable to var
so I’m facing a dilemma : words
should be a var
(allowing a new instance of map to be used for each iteration) if results are to be stored in an immutable Map
while turning words
into a val
implies to use a mutable Map
.
Could someone enlighten me about the proper way to deal with this existential problem?
In this case you can use groupBy
and mapValues
:
val tokens = poe_m.stripMargin.split(separators).filterNot(_.isEmpty)
val words = tokens.groupBy(w => w).mapValues(_.size)
More generally this is a job for a fold:
val words = tokens.foldLeft(Map.empty[String, Int]) {
case (m, t) => m.updated(t, m.getOrElse(t, 0) + 1)
}
The Wikipedia entry on folds gives some good clarifying examples.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With