如何以正确的Scala函数方式编写以下代码段?

lic*_*rna 0 functional-programming scala

我是Scala的新手,想知道这是否是正确的写作方式:

def createCol(prior: List[Int], current: List[Int]): List[Int] = {
  if (prior.isEmpty) List(1) ++ current
  else if (prior.tail.isEmpty)   // begin of the block to improve
    createCol(prior.tail, current ++ List(prior.head))
  else
    createCol(prior.tail, current ++ List(prior.head + prior.tail.head))
}
Run Code Online (Sandbox Code Playgroud)

我感兴趣的部分是这样的:

if (prior.tail.isEmpty)
  createCol(prior.tail, current ++ List(prior.head))
else
  createCol(prior.tail, current ++ List(prior.head + prior.tail.head))
Run Code Online (Sandbox Code Playgroud)

因为我正在重复几乎相同的函数调用,createCol所以我尝试了这个:

val ssum = if (prior.tail.isEmpty) prior.head else prior.head + prior.tail.head
createCol(prior.tail, current ++ List(ssum))
Run Code Online (Sandbox Code Playgroud)

这样做的最佳或推荐方法是什么?

谢谢

dhg*_*dhg 7

几点:

  1. 我将您的函数更改为使用Scala的模式匹配框架,因为它极大地简化了代码.

  2. 你不应该这样做,List(x) ++ someList因为这会不必要地构造一个单项列表.您应该只使用prepend方法::(或+:).附加(:+)也是如此.

  3. 如果prior只有一个元素,那么你知道所有的递归调用都会1在前面添加current.所以你可以从第二种情况中删除递归调用.

  4. 你的方法是尾递归的,所以用它来注释它@tailrec.

  5. 最后,考虑使用a Vector而不是List.追加到a List是O(n),因为该方法必须一直遍历到最后(然后从后面到前面重建List).但前提和追加的Vector都是有效的O(1).

所以:

@tailrec
def createCol(prior: List[Int], current: List[Int]): List[Int] = {
  prior match {
    case Nil => 1 :: current
    case head :: Nil => 1 +: current :+ head
    case head :: tail => createCol(tail, current :+ (head + tail.head))
  }
}
Run Code Online (Sandbox Code Playgroud)

您也可以在两种情况下执行此操作,就像您在问题中所描述的那样.但是你应该使用该headOption方法而不是显式地执行if/else:

@tailrec
def createCol(prior: List[Int], current: List[Int]): List[Int] = {
  prior match {
    case Nil =>
      1 :: current
    case head :: tail =>
      createCol(tail, current ++ List(head + tail.headOption.getOrElse(0)))
  }
}
Run Code Online (Sandbox Code Playgroud)