如何将单词列表计入Map结构中,其中Int是count,String是当前单词。
我正在尝试使用折叠,但这是我最接近的:
val links = List("word1" , "word2" , "word3")
links.fold(Map.empty[String, Int]) ((count : Int, word : String) => count + (word -> (count.getOrElse(word, 0) + 1)))
导致错误:
value getOrElse is not a member of Int
答案 0 :(得分:2)
也许不是最有效的,但对我来说最明智的方式是:
val grouped = links groupBy { identity } // Map[String, List[String]]
val summed = grouped mapValues { _.length } // Map[String, Int]
println(grouped) // Map(word2 -> List(word2, word2), word1 -> List(word1))
println(summed) // Map(word2 -> 2, word1 -> 1)
答案 1 :(得分:2)
如果你看看折叠的签名,你可以看到
links.fold(Map.empty[String, Int]) ((count : Int, word : String) => ???)
不会编译
<{1}}上的折叠类型为List[A]
这不是你可以使用的东西; fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
不是Map.empty[String, Int]
您需要的是String
:foldLeft
您的foldLeft[B](z: B)(op: (B, A) ⇒ B): B
是A
。您的String
为B
,但是在您的第二个参数列表中,您Map[String, Int]
并不符合签名。它应该是(Int, String) => ???
立即出现解决方案:
(Map[String, Int], String) => Map[String, Int]
总而言之,你有
(map: Map[String, Int], next : String) => map + (next, map.get(next).getOrElse(0) + 1)
答案 2 :(得分:1)
您需要使用foldLeft:
val links = List("word1" , "word2" , "word3", "word3")
val wordCount = links.foldLeft(Map.empty[String, Int])((map, word) => map + (word -> (map.getOrElse(word,0) + 1)))
答案 3 :(得分:1)
这是一个例子,其中cats或scalaz这样的库的一些抽象是有用的,并提供了一个很好的解决方案。
我们可以将"foo"
代表Map("foo" -> 1)
。如果我们可以将这些地图组合成所有单词,那么我们最终会得到单词count。这里的关键字是 combine ,它是Semigroup
中定义的函数。我们可以使用此函数将我们单词列表的所有地图组合在一起使用combineAll
(在Foldable
中定义并为您进行折叠)。
import cats.implicits._
val words = List("a", "a", "b", "c", "c", "c")
words.map(i => Map(i -> 1)).combineAll
// Map[String,Int] = Map(b -> 1, a -> 2, c -> 3)
或使用foldMap
一步完成:
words.foldMap(i => Map(i -> 1))
// Map[String,Int] = Map(b -> 1, a -> 2, c -> 3)