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
在这种情况下,您可以使用groupBy
和mapValues
:
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)