2016-07-12 101 views
0

单词列表如何计入Map结构,其中Int是计数,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 

回答

2

如果你看一看倍的签名,你可以看到

links.fold(Map.empty[String, Int]) ((count : Int, word : String) => ???) 

不会编译

List[A]倍的类型为fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1

这是不是你可以使用; Map.empty[String, Int]不是String

一个亚型,你需要的是foldLeftfoldLeft[B](z: B)(op: (B, A) ⇒ B): B

AString。您的BMap[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) 

全部放在一起,你就会有

links.foldLeft(Map.empty[String, Int]) 
((map: Map[String, Int], next : String) => map + (next, map.get(next).getOrElse(0) + 1)) 
+0

@Martjin代码“links.fold(Map.empty [字符串,INT]) (地图:地图[字符串,INT],下一:String)=> map +(next,map.get(next))。getOrElse(0)+ 1)“会导致编译时错误”traitableOnce中缺少方法折叠的参数;如果您想将其视为部分应用的功能,请使用'_'执行此操作。“ – thepen

+0

您忘记在最后一行用'foldLeft'代替'fold'。 –

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

您需要使用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))) 
1

这是一个例子,其中一些图书馆的抽象如catsscalaz是有用的,并提供一个很好的解决方案。

我们可以将单词"foo"表示为Map("foo" -> 1)。如果我们可以将这些地图合并为我们所有的单词,我们最终会得到单词计数。这里的关键字是组合,这是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)