[英]How to write the following snippet in a correct Scala functional way?
我是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))
}
我感興趣的部分是:
if (prior.tail.isEmpty)
createCol(prior.tail, current ++ List(prior.head))
else
createCol(prior.tail, current ++ List(prior.head + prior.tail.head))
由於我要重復幾乎相同的函數調用createCol
因此我嘗試了以下方法:
val ssum = if (prior.tail.isEmpty) prior.head else prior.head + prior.tail.head
createCol(prior.tail, current ++ List(ssum))
最好或推薦的方法是什么?
謝謝
幾點:
我將您的功能更改為使用Scala的模式匹配框架,因為它極大地簡化了您的代碼。
您不應該執行List(x) ++ someList
因為這樣會不必要地構造單項列表。 您應該只使用prepend方法::
:(或+:
:)。 追加( :+
)也一樣。
如果prior
只有一個元素,則您將要進行的所有遞歸調用都將1
放在current
的前面。 因此,您可以從第二種情況中刪除遞歸調用。
您的方法是尾遞歸的,因此請使用@tailrec
對其進行@tailrec
。
最后,考慮使用Vector
而不是List
。 追加到List
是O(n),因為該方法必須一直遍歷到底(然后從后到前重建列表)。 但是,在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))
}
}
您也可以在兩種情況下這樣做,就像您在問題中描述的那樣。 但是您應該使用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)))
}
}
您的功能似乎等同於以下內容:
def createCol(prior: List[Int], current: List[Int]) =
if (prior.isEmpty) 1 :: current
else 1 :: current ::: (prior, prior.tail :+ 0).zipped.map(_ + _)
或使用Vector
,如果列表很長,則應該在添加和添加時表現出更好的性能:
def createCol(prior: Vector[Int], current: Vector[Int]) =
if (prior.isEmpty) 1 +: current
else (1 +: current) ++ (prior, prior.tail :+ 0).zipped.map(_ + _)
這樣可以避免遞歸,而且我認為可以很清楚地看到未修改current
,無論如何都只是添加1
,並且prior自身與最后一個元素的偏移量為1(與0
求和),然后附加到current上。
甚至避免重復(1 +:current):
(1 +: current) ++ (
if (prior.isEmpty) Vector()
else (prior, prior.tail :+ 0).zipped.map(_ + _))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.