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)
这样做的最佳或推荐方法是什么?
谢谢
几点:
我将您的函数更改为使用Scala的模式匹配框架,因为它极大地简化了代码.
你不应该这样做,List(x) ++ someList
因为这会不必要地构造一个单项列表.您应该只使用prepend方法::
(或+:
).附加(:+
)也是如此.
如果prior
只有一个元素,那么你知道所有的递归调用都会1
在前面添加current
.所以你可以从第二种情况中删除递归调用.
你的方法是尾递归的,所以用它来注释它@tailrec
.
最后,考虑使用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)