scala模式匹配 - 变量

时间:2011-08-29 01:36:38

标签: scala pattern-matching

在我阅读this (page 14)时,我遇到了这个算法:

function fib2(n)
    if n = 0 return 0
    create an array f[0 : : : n]
    f[0] = 0, f[1] = 1
    for i = 2 : : : n:
        f[i] = f[i  1] + f[i  2]
    return f[n]

如果我想使用模式匹配在Scala中实现它,有没有办法在模式匹配部分创建一个List,以便在最终的return语句中使用它?

这些都是很好的答案,但我想我仍然想知道是否可以定义一个仅在模式匹配中使用的变量。我知道你可以在Haskell中做到这一点,但我想知道它是否在Scala中可行。

4 个答案:

答案 0 :(得分:13)

lazy val fib: Stream[Int] = Stream.cons(0,Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2)))

fib.take(n).last 将返回结果
另一种流解决方案。它定义了无限的斐波纳契数列。是的,它是救援和无限定义,但所有计算都是在调用take时执行的 enter image description here 只需在这里查看更多有趣的代码。 link

答案 1 :(得分:10)

我认为这里不需要模式匹配。对Scala的直接转换看起来基本相同:创建一个数组f并循环遍历索引2 until n

def fib(n: Int): Array[Int] = {
  val f = new Array[Int](math.max(2, n))
  f(0) = 0
  f(1) = 1
  for (i <- 2 until n)
    f(i) = f(i-1) + f(i-2)
  f
}

如果你想变得更加漂亮,lazy stream怎么样?

def fibFrom(a: Int, b: Int): Stream[Int] = a #:: fibFrom(b, a + b)
fibFrom(0, 1).take(8).toList // returns List(0, 1, 1, 2, 3, 5, 8, 13)

答案 2 :(得分:2)

以下是jeela解决方案的重构。我认为最好始终与头部一起工作,因为它要快得多。最终的reverse并没有太大的伤害。

def fib(s:Int) = {
  def f(s:Int):List[Int] = s match {
    case x if x < 0 => Nil
    case 0 => List(0)
    case 1 => List(1,0)
    case _ => val fibs = f(s-1); (fibs.head + fibs.tail.head) :: fibs
  }
  f(s).reverse
}

答案 3 :(得分:1)

我认为使用懒惰流是更好的方法,但只是为了展示我的肌肉:

def fib(s:Int):List[Int] = s match {
  case 0 => Nil
  case 1 => 0::fib(s-1)
  case 2 => 0::1::fib(s-2)
  case _ => fib(s-1):::fib(s-1).takeRight(2).sum::Nil
}