我正在学习本书 scala中的函数式编程。第10章,练习20,实施以下方法:
def frequencyMap(strings: IndexedSeq[String]): Map[String, Int]
老实说,我没有解决方案,所以,我检查了GIT的答案:
def mapMergeMonoid[K, V](V: Monoid[V]): Monoid[Map[K, V]] =
new Monoid[Map[K, V]] {
def zero = Map()
def op(a: Map[K, V], b: Map[K, V]) =
a.map {
case (k, v) => (k, V.op(v, b.get(k) getOrElse V.zero))
}
}
def bag[A](as: IndexedSeq[A]): Map[A, Int] =
foldMapV(as, mapMergeMonoid[A, Int](intAddition))((a: A) => Map(a -> 1))
def frequencyMap(strings: IndexedSeq[String]): Map[String, Int] = bag(strings)
但是,当我试图进行测试时,答案得错了:
frequencyMap(Vector("a rose", "is a", "rose is", "a rose"))
打印出答案:
Map(a rose -> 1)
预期结果:
Map(a -> 3, rose -> 3, is -> 2)
我无法弄清楚实施的错误。有人可以帮我解释一下吗?谢谢。
在正确答案后进行编辑,并使用正确的实施进行更新
def mapMergeMonoid[K, V](V: Monoid[V]): Monoid[Map[K, V]] =
new Monoid[Map[K, V]] {
def zero = Map()
def op(a: Map[K, V], b: Map[K, V]) = {
// (a.map {
// case (k, v) => (k, V.op(v, b.get(k) getOrElse V.zero))
//
val c = for {
(ka, va) <- a
(kb, vb) <- b
if (ka == kb)
} yield (ka -> V.op(va, vb))
a ++ b ++ c
}
}
def bag[A](as: IndexedSeq[A]): Map[A, Int] =
foldMapV(as, mapMergeMonoid[A, Int](intAddition))((a: A) => Map(a -> 1))
def frequencyMap(strings: IndexedSeq[String]): Map[String, Int] = bag(strings.map(_.split("\\s+")).flatten)
答案 0 :(得分:1)
我没有这本书,但是按照here的代码,我可以指出一些事情供您考虑(基于REPL会话中的一些println()):
正如S.R.I指出的那样,你有一个短语列表,而不是单词。 github上的函数没有做任何事情来为你分隔单词组,所以最好,你当前的输入Vector可以得到:
Map(a rose -> 2, is a -> 1, rose is -> 1)
您可以通过对Vector执行以下操作来创建单词列表:
Vector("a rose", "is a", "rose is", "a rose") map( _.split( " " ).toSeq ) flatten
仅当键(k)相同时,mapMergeMonoid
函数才会出现将k和v的值相加。意味着未排序的列表将导致大量Map(string -> 1)
。
您可以通过对Vector进行以下更改来对单词Vector进行排序:
(Vector("a rose", "is a", "rose is", "a rose") map( _.split( " " ).toSeq ) flatten) sortWith(_.compareTo(_) < 0)
虽然foldMapV
确实在Map[String, Int]
中拆分了Vector中的所有短语或单词,但它似乎只返回已排序的IndexedSeq最左边的所需合并。根据我已经指出的排序的单词向量,我从Map(a -> 3)
的实现中得到了结果frequencyMap
。我倾向于使用foldMapV
之外的其他内容,或者修改它以使frequencyMap
起作用。对我来说似乎缺少的一点是它应用于一个大Map的函数结果的累积。我还会尝试比splitAt()调用更“标准”的头/尾递归(因为我不相信foldMapV
处理is
和rose
非常好。)< / p>