声明
该系列文章来自:http://aperiodic.net/phil/scala/s-99/
大部分内容和原文相同,加入了部分自己的代码。
如有侵权,请及时联系本人。本人将立即删除相关内容。

P06 (*) Find out whether a list is a palindrome.

要求

判断一个list是不是回文

Example:

1
2
scala> isPalindrome(List(1, 2, 3, 2, 1))
res0: Boolean = true

方案

  • (1) 反转list之后和自身反转之前的元素顺序一致
1
2
def isPalindrome1[T](list: List[T]): Boolean =
list == list.reverse

P07 (**) Flatten a nested list structure.

要求

将一个内嵌N重list的list所有元素提取至一个新的list,新的list不能嵌套list结构

Example:

1
2
scala> flatten(List(List(1, 1), 2, List(3, List(5, 8))))
res0: List[Any] = List(1, 1, 2, 3, 5, 8)

方案

  • (1) 递归+List.flatMap
1
2
3
4
def flatten(list: List[Any]): List[Any] = list.flatMap {
case ls: List[_] => flatten(ls)
case e => List(e)
}

P08 (**) Eliminate consecutive duplicates of list elements.

要求

If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.

Example:

1
2
scala> compress(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))
res0: List[Symbol] = List('a, 'b, 'c, 'a, 'd, 'e)

方案

  • (1) List.dropWhile + recursive
1
2
3
4
def compressRecursive[T](list: List[T]): List[T] = list match {
case Nil => Nil
case h :: tail => h :: compressRecursive(tail.dropWhile(e => e == h))
}
  • (2) List.dropWhile + tail-recursive
1
2
3
4
5
6
7
8
def compressTailRecursive[T](list: List[T]): List[T] = {
def compressR(ret: List[T], ls: List[T]): List[T] = ls match {
case Nil => ret
case h :: tail => compressR(ret ::: List(h), ls.dropWhile(_ == h))
}
return compressR(Nil, list)
}
  • (3) List.dropWhile + tail-recursive
1
2
3
4
5
6
7
8
def compressTailRecursive2[T](list: List[T]): List[T] = {
def compressR(ret: List[T], ls: List[T]): List[T] = ls match {
case Nil => ret.reverse
case h :: tail => compressR(h :: ret, ls.dropWhile(_ == h))
}
return compressR(Nil, list)
}
  • (4) foldRight
1
2
3
4
5
6
7
def compressFunctional[A](ls: List[A]): List[A] =
ls.foldRight(List[A]()) { (h, r) =>
if (r.isEmpty || r.head != h)
h :: r
else
r
}

P09 (**) Pack consecutive duplicates of list elements into sublists.

要求

If a list contains repeated elements they should be placed in separate sublists.

Example:

1
2
scala> pack(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))
res0: List[List[Symbol]] = List(List('a, 'a, 'a, 'a), List('b), List('c, 'c), List('a, 'a), List('d), List('e, 'e, 'e, 'e))

方案

  • (1) span + 普通递归
1
2
3
4
5
6
7
8
9
def pack2[T](list: List[T]): List[List[T]] = list match {
case Nil => List(List())
case ls: List[T] => {
val (packed, tail) = ls.span(_ == ls.head)
if (tail == Nil)
List(packed)
else packed :: pack2(tail)
}
}
  • (2) span + 尾递归
1
2
3
4
5
6
7
8
9
10
def pack[T](list: List[T]): List[List[T]] = {
def packR(ret: List[List[T]], ls: List[T]): List[List[T]] = ls match {
case Nil => ret
case head :: tail => {
val (l, r) = (head :: tail).span(_ == head)
packR(ret ::: List(l), r)
}
}
return packR(Nil, list)
}

P10 (*) Run-length encoding of a list.

要求

Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as tuples (N, E) where N is the number of duplicates of the element E.

Example:

1
2
scala> encode(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e))
res0: List[(Int, Symbol)] = List((4,'a), (1,'b), (2,'c), (2,'a), (1,'d), (4,'e))

方案

  • (1) map
1
2
def encode[T](list: List[T]): List[(Int, T)] =
pack(list).map(e => (e.length, e.head))