[英]Scala equivalent of Haskell's insertWith for Maps
I'm looking to do the simple task of counting words in a String. 我正在寻找计算字符串中单词的简单任务。 The easiest way I've found is to use a Map to keep track of word frequencies.
我发现最简单的方法是使用Map来跟踪单词频率。 Previously with Haskell, I used its
Map
's function insertWith
, which takes a function that resolves key collisions, along with the key and value pair. 以前使用Haskell,我使用了
Map
的函数insertWith
,它使用一个解决键冲突的函数,以及键和值对。 I can't find anything similar in Scala's library though; 我在Scala的库中找不到类似的东西; only an add function (
+
), which presumably overwrites the previous value when re-inserting a key. 只有一个add函数(
+
),它可能会在重新插入一个键时覆盖之前的值。 For my purposes though, instead of overwriting the previous value, I want to add 1 to it to increase its count. 虽然我的目的,而不是覆盖以前的值,我想添加1来增加它的数量。
Obviously I could write a function to check if a key already exists, fetch its value, add 1 to it, and re-insert it, but it seems odd that a function like this isn't included. 显然我可以编写一个函数来检查一个密钥是否已经存在,获取它的值,向它添加1,然后重新插入它,但是这样的函数不包括在内似乎很奇怪。 Am I missing something?
我错过了什么吗? What would be the Scala way of doing this?
Scala的做法是什么?
Use a map with default value and then update with +=
使用具有默认值的地图,然后使用
+=
进行更新
import scala.collection.mutable
val count = mutable.Map[String, Int]().withDefaultValue(0)
count("abc") += 1
println(count("abc"))
If it's a string then why not use the split module 如果它是一个字符串,那么为什么不使用split模块
import Data.List.Split
let mywords = "he is a good good boy"
length $ nub $ splitOn " " mywords
5
If you want to stick with Scala's immutable style, you could create your own class with immutable semantics: 如果你想坚持使用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))
}
And then you can use it: 然后你可以使用它:
val added = CountMap() + "hello" + "hello" + "world" + "foo" + "bar"
added("hello")
>>2
added("qux")
>>0
You might also add apply
overloads on the companion object so that you can directly input a sequence of words, or even a sentence: 您还可以在随播对象上添加
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(" "))
}
And then the you can even more easily: 然后你可以更轻松地:
CountMap(Seq("hello", "hello", "world", "world", "foo", "bar"))
Or: 要么:
CountMap("hello hello world world foo bar")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.