当您发现字符重复时,您将附加到错误的列表中。我摆弄的结果:
object P08SO extends App {
// this method packs by adding to the beginning of the result and at the end it uses reverse
def pack1[A](inputList: List[A]): List[List[A]] = {
@tailrec
def checkNext(result: List[List[A]], prev: A, input: List[A]): List[List[A]] =
if (input.isEmpty) result
else
checkNext(
if (input.head == prev) (input.head :: result.head) :: result.tail
else List(input.head) :: result,
input.head, input.tail)
if (inputList.isEmpty) Nil
else checkNext(List(List(inputList.head)), inputList.head, inputList.tail).reverse
}
// packs directly in right order
// but IMO there's a quite significant performance cost (last and init have to iterate through entire list)
def pack2[A](inputList: List[A]): List[List[A]] = {
@tailrec
def checkNext(result: List[List[A]], prev: A, input: List[A]): List[List[A]] =
if (input.isEmpty) result
else
checkNext(
if (input.head == prev) result.init ::: List(input.head :: result.last)
else result ::: List(List(input.head)),
input.head, input.tail)
if (inputList.isEmpty) Nil
else checkNext(List(List(inputList.head)), inputList.head, inputList.tail)
}
List[(String, List[Any])](
"empty" -> List(),
"one string" -> List("str"),
"ints" -> List(0, 0, 0, 1, 1, 2, 3, 4, 4, 4, 4, 5, 6),
"chars" -> "abbbcdeeffff".toList
).foreach(
testVal => {
println(s"pack1 - ${testVal._1}: ${pack1(testVal._2)}")
println(s"pack2 - ${testVal._1}: ${pack2(testVal._2)}")
}
)
}
输出:
pack1 - empty: List()
pack2 - empty: List()
pack1 - one string: List(List(str))
pack2 - one string: List(List(str))
pack1 - ints: List(List(0, 0, 0), List(1, 1), List(2), List(3), List(4, 4, 4, 4), List(5), List(6))
pack2 - ints: List(List(0, 0, 0), List(1, 1), List(2), List(3), List(4, 4, 4, 4), List(5), List(6))
pack1 - chars: List(List(a), List(b, b, b), List(c), List(d), List(e, e), List(f, f, f, f))
pack2 - chars: List(List(a), List(b, b, b), List(c), List(d), List(e, e), List(f, f, f, f))