【问题标题】:recursively computing the product of the Unicode codes of all letters in a string递归计算字符串中所有字母的Unicode代码的乘积
【发布时间】:2012-07-04 00:31:09
【问题描述】:

我有点讨厌递归(这就是我研究这个的原因)而且我很难弄清楚如何做到这一点:("Hello" foldLeft(1))((x, y) => x * y.toInt) 递归。有什么想法吗?

【问题讨论】:

  • 更好:"Hello".map(_.toInt).product

标签: scala recursion


【解决方案1】:
scala> def r(s : String) : Int = {
 | s match { 
 | case "" => 1
 | case _ => s.head.toInt * r(s.tail)
 | }
 | }
r: (s: String)Int

scala> r("hello")
res4: Int = 714668928

【讨论】:

  • @LuxuryMode -- 不行。在方法上加上@tailrec注解,如果不是,编译器会报错
  • @LuxuryMode:对于尾递归的函数,最后一个表达式必须是对函数本身的调用。在这种情况下,最后一个表达式是乘法。
【解决方案2】:

我将另一个答案转换为我认为的尾递归版本:

@tailrec
def r(acc: Int, s: String): Int = {
  s match {
    case "" => acc
    case _ => r(s.head.toInt * acc, s.tail)
  }
}

print(r(1, "hello"))

有关将此类函数转换为尾递归格式的一般建议,请参阅此答案:

Isn't that code in tail recursive style?

【讨论】:

  • 感谢大卫,这太棒了!不知道@tailrec 注释..太酷了。
  • 我宁愿写r(s:String, acc:Int = 1),这样调用函数的时候就不用初始化累加器了。
【解决方案3】:

这是一个使用累加器的尾递归版本。这个版本也有一个干净的 API。

import scala.annotation.tailrec

def unicodeProduct(string: String): Int = {
  @tailrec
  def unicodeProductAcc(string: String, acc: Int): Int = {
    string match{
      case "" => acc
      case _ => unicodeProductAcc(string.tail, string.head.toInt * acc )
    }
  }
  unicodeProductAcc(string, 1)
}


scala> :load unicodeProduct.scala
Loading unicodeProduct.scala...
import scala.annotation.tailrec
unicodeProduct: (string: String)Int


scala> unicodeProduct("hello")
res0: Int = 714668928

【讨论】:

  • 拥有嵌套函数的能力真是太棒了。让您编写真正干净的 API。在 java 中,你会有一堆私有方法,即使它们只在一个方法中用作子例程。
【解决方案4】:

过时了,但下面有什么问题?

  def product_recursive(s: String): Long = {
      if (s.length == 1) 
        s.head.toLong
      else 
        s.head.toLong * product_recursive(s.tail)
  }

【讨论】:

  • 与接受的答案几乎相同,除了这个不会处理空字符串""
猜你喜欢
  • 2020-03-15
  • 2013-07-21
  • 1970-01-01
  • 1970-01-01
  • 2015-08-12
  • 2015-12-01
  • 2020-08-27
  • 2014-03-31
  • 1970-01-01
相关资源
最近更新 更多