我尝试使用递归从here解决问题13,但是我收到了错误(我不明白)。
问题是:
给出以下列表List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)
我需要返回重复的元素并计算:
List((4,'a), (1,'b), (2,'c), (2,'a), (1,'d), (4,'e))
这是我的代码:
object P13 extends App {
val ls2 = List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)
println(ls2)
println(encodeDirect(ls2))
def encodeDirect[A](ls: List[A]): List[(Int,A)] = ls match {
case h :: tail => (ls.takeWhile( _ == h ).count(_), h) +: encodeDirect (ls.dropWhile ( _ == h ) )
case Nil => Nil
}
}
这是错误:
P13.scala:18: error: type mismatch;
found : List[(Any, A)]
required: List[(Int, A)]
case h :: tail => (ls.takeWhile( _ == h ).count(_), h) +: encodeDirect
(ls.dropWhile ( _ == h ) )
^
one error found
为什么会发生这种情况以及如何解决这个问题?
答案 0 :(得分:1)
您的错误非常简单,您使用count
代替size
/ length
:
def encodeDirect[A](ls: List[A]): List[(Int,A)] = ls match {
case h :: tail => (ls.takeWhile( _ == h ).size, h) +: encodeDirect (ls.dropWhile ( _ == h ) )
case Nil => Nil
}
count
获取谓词并计算与该谓词匹配的元素数,而size
只返回集合的长度。
只是为了好玩,这里有一个替代方案,利用span
将集合分解为前缀/后缀:
def encodeDirect[A](ls: List[A]): List[(Int,A)] =
ls.headOption.map(h => ls.span(h == _)).toList
.flatMap { case (pref, t) => (pref.size, pref.head) :: encodeDirect(t) }
使用结果累加器作为参数,以尾递归方式重写此函数也是一个好主意,因为尾递归在scala中更有效。
答案 1 :(得分:0)
另一种方法,使用span
,
def encode(xs: List[Symbol]): List[(Int,Symbol)] = xs match {
case Nil => Nil
case x :: xss => val (g,rest) = xs.span(_ == x)
(g.size,g.head) +: encode(rest)
}
我们首先将列表分成与头部相同的项目,然后是其余部分。