在循环中填充地图[Scala]

Jer*_*ERT 4 for-loop scala map

我担心这是另一个菜鸟问题.

我想要做的是使用a Map来计算一个单词出现在poe ...中的频率,然后将结果打印到控制台.我转到下面的代码,我相信它正在工作(虽然可能不是很惯用):

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))
Run Code Online (Sandbox Code Playgroud)

据我明白,在Scala中,不可变的数据结构是优选的,以可变的那些和val优选var所以我面临两难:words应该是var(允许地图的新实例被用于每次迭代)如果结果是是存储在一个不可变的 Map同时words变成一个val暗示使用一个mutable Map.

有人可以告诉我处理这个存在问题的正确方法吗?

Tra*_*own 10

在这种情况下,您可以使用groupBymapValues:

val tokens = poe_m.stripMargin.split(separators).filterNot(_.isEmpty)
val words = tokens.groupBy(w => w).mapValues(_.size)
Run Code Online (Sandbox Code Playgroud)

更一般地说,这是一个折叠的工作:

 val words = tokens.foldLeft(Map.empty[String, Int]) {
   case (m, t) => m.updated(t, m.getOrElse(t, 0) + 1)
 }
Run Code Online (Sandbox Code Playgroud)

关于折叠维基百科条目提供了一些很好的澄清示例.

  • 而不是`w => w`可以使用`identity` (2认同)