簡體   English   中英

Scala相當於Haskell的insertWith for Maps

[英]Scala equivalent of Haskell's insertWith for Maps

我正在尋找計算字符串中單詞的簡單任務。 我發現最簡單的方法是使用Map來跟蹤單詞頻率。 以前使用Haskell,我使用了Map的函數insertWith ,它使用一個解決鍵沖突的函數,以及鍵和值對。 我在Scala的庫中找不到類似的東西; 只有一個add函數( + ),它可能會在重新插入一個鍵時覆蓋之前的值。 雖然我的目的,而不是覆蓋以前的值,我想添加1來增加它的數量。

顯然我可以編寫一個函數來檢查一個密鑰是否已經存在,獲取它的值,向它添加1,然后重新插入它,但是這樣的函數不包括在內似乎很奇怪。 我錯過了什么嗎? Scala的做法是什么?

使用具有默認值的地圖,然后使用+=進行更新

import scala.collection.mutable

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

如果它是一個字符串,那么為什么不使用split模塊

import Data.List.Split

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

如果你想堅持使用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")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM