我刚开始学习Scala和函数式编程,我正在尝试将以下内容从Python转换为Scala:
def immutable_iterative_fibonacci(position):
if (position ==1):
return [1]
if (position == 2):
return [1,1]
next_series = lambda series, _: series + [series [-1] + series [-2]]
return reduce(next_series, range(position - 2), [1, 1])
我无法弄清楚Scala中等效的reduce是什么。这就是我现在拥有的。除了最后一行,一切正常。
def immutable_fibonacci(position: Int) : ArrayBuffer[Int] = {
if (position == 1){
return ArrayBuffer(1)
}
if (position == 2){
return ArrayBuffer(1,1)
}
var next_series = (series: ArrayBuffer[Int]) => series :+ ( series( series.size - 1) + series( series.size -2))
return reduce(next_series, 2 to position, ArrayBuffer(1,1))
}
答案 0 :(得分:11)
Python reduce
摘要,供参考:
reduce(function, iterable[, initializer])
要查看的好类型是Traversable
,是ArrayBuffer
的超类型。您可能只想暂时使用该API,因为那里有很多有用的东西。
当省略reduce
arg时,相当于Python的initializer
是Scala的Traversable[A]#reduceLeft
:
reduceLeft[B >: A](op: (B, A) => B): B
Python函数中的iterable
arg对应Traversable
实例,Python函数中的function
arg对应op
。
请注意,还有一些名为reduce
,reduceRight
,reduceLeftOption
和reduceRightOption
的方法,它们相似但略有不同。
您提供initializer
arg的示例与Scala的Traversable[A]#foldLeft
对应:
foldLeft[B](z: B)(op: (B, A) => B): B
Python函数中的initializer
arg对应z
中的foldLeft
arg。
再次注意,有一些名为fold
和foldRight
的相关方法。
在不更改算法的情况下,这是代码的清理版本:
def fibonacci(position: Int): Seq[Int] =
position match {
case 1 => Vector(1)
case 2 => Vector(1, 1)
case _ =>
(2 to position).foldLeft(Vector(1, 1)) { (series, _) =>
series :+ (series(series.size - 1) + series(series.size - 2))
}
}
一些杂项说明:
return
关键字match
关键字执行的操作)通常被认为比if
- else
链更清晰var
(允许多次转让)替换为val
(不允许)ArrayBuffer
)。 Vector
是一个很好的通用不可变序列。虽然我们正在讨论馆藏和斐波那契系列的主题,但为了好玩,您可以查看Stream
文档中的第一个示例:
val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #::
fibs.zip(fibs.tail).map { n => n._1 + n._2 }
fibs.drop(1).take(6).mkString(" ")
// "1 1 2 3 5 8"