Scala相当于Haskell的insertWith for Maps

时间:2015-02-14 01:48:44

标签: scala dictionary

我正在寻找计算字符串中单词的简单任务。我发现最简单的方法是使用Map来跟踪单词频率。以前使用Haskell时,我使用了Map的函数insertWith,该函数采用了解决键冲突的函数以及键和值对。我在Scala的库中找不到类似的东西;只有一个添加函数(+),可能会在重新插入密钥时覆盖以前的值。但是,出于我的目的,我想添加1以增加其数量,而不是覆盖之前的值。

显然我可以编写一个函数来检查一个密钥是否已经存在,获取它的值,向它添加1,然后重新插入它,但是这样的函数不包括在内似乎很奇怪。我错过了什么吗? Scala的做法是什么?

3 个答案:

答案 0 :(得分:3)

使用具有默认值的地图,然后使用+=

进行更新
import scala.collection.mutable

val count = mutable.Map[String, Int]().withDefaultValue(0)
count("abc") += 1
println(count("abc"))

答案 1 :(得分:0)

如果它是一个字符串,那么为什么不使用拆分模块

import Data.List.Split

let mywords = "he is a good good boy"
length $ nub $ splitOn " " mywords
5

答案 2 :(得分:0)

如果你想坚持使用Scala的不可变样式,你可以使用不可变的语义创建自己的类:

class CountMap protected(val counts: Map[String, Int]){
    def +(str: String) = new CountMap(counts + (str -> (counts(str) + 1)))
    def apply(str: String) = counts(str)
}

object CountMap {
    def apply(counts: Map[String, Int] = Map[String, Int]()) = new CountMap(counts.withDefaultValue(0))
}

然后你可以使用它:

val added = CountMap() + "hello" + "hello" + "world" + "foo" + "bar"
added("hello")
>>2
added("qux")
>>0

您还可以在随播对象上添加apply重载,以便您可以直接输入单词序列,甚至是句子:

object CountMap {
    def apply(counts: Map[String, Int] = Map[String, Int]()): CountMap = new CountMap(counts.withDefaultValue(0))
    def apply(words: Seq[String]): CountMap = CountMap(words.groupBy(w => w).map { case(word, group) => word -> group.length })
    def apply(sentence: String): CountMap = CountMap(sentence.split(" "))
}

然后你就可以更容易了:

CountMap(Seq("hello", "hello", "world", "world", "foo", "bar"))

或者:

CountMap("hello hello world world foo bar")