Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populating a map in a loop [Scala]

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 varso 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?

like image 819
Jerome ROBERT Avatar asked Dec 04 '22 16:12

Jerome ROBERT


1 Answers

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.

like image 91
Travis Brown Avatar answered Dec 19 '22 00:12

Travis Brown