【问题标题】:Initial value in loops循环中的初始值
【发布时间】:2013-12-04 23:58:34
【问题描述】:

假设您正在编写一个尾递归循环函数来根据某些标准评估元素集合,并希望最终得到得分最高的元素及其得分。

您自然会将目前为止得分最高的元素及其得分作为参数传递给函数。

但是由于在递归开始时没有最佳元素,您最初应该将什么作为参数传递给循环函数?不想使用 null,您可以使用 Option[T] 作为参数类型,但是您必须在每次递归时检查 isEmpty,同时您知道它在初始调用后总是有一个值。没有更好的办法吗?

【问题讨论】:

  • 你能做类似( xs map ( x => (score(x),x) ) ).max的事情吗?
  • 这看起来不错,但一个缺点是您需要对集合进行两次迭代。
  • 绝对!如果您的应用程序运行速度太慢并且分析显示此代码对问题有很大影响,那么您需要trade off maintainability for performance。在这种情况下,由 3 个参数(xs、hiScore 和 hiScorer)组成的尾递归解决方案几乎可以肯定是表现最好的,它可以让您按照 herman 的要求访问最高得分者及其得分。
  • 我想我应该补充一点,如果xs 没有订购,或者如果比较它们非常昂贵(以上将比较它们的平局分数),你可以取最大值像这样的分数:( xs map ( x => (score(x),x) ) ).maxBy(_._1)

标签: scala recursion


【解决方案1】:

您可以使用 list.head 作为初始值并循环列表。第一次评估将被“浪费”,因为您正在根据自身评估 list.head ,但这将计算 list.head 的分数,并且其余的迭代可以继续并做您想做的事情。

【讨论】:

  • 这意味着list.tail中的任何元素都比list.head得分高,这不一定是正确的。
  • 但是使用list.head作为初始值并循环list会导致list.head的分数被重新评估为正确的值。如果您更改答案以反映这一点,我会接受。
  • @herman 好点。我很困惑,并认为我们会使用初始值来开始。固定。
  • 注意在空列表上调用head会抛出异常。
  • @KevinMeredith 没错,我认为这就是在这种情况下想要的行为。否则,很容易调用headOption 并将函数的返回类型更改为Option[T]
【解决方案2】:

如何评估“最佳元素”?

通常这是通过数值完成的。

一开始,您通常将该值设置为一个数字。最佳实践表明该数字应定义为常量,类似于 MIN_VALUE 的名称。该值可以是零、负数或可表示的最小浮点数。

【讨论】:

  • 我认为链接适合您的Best practices state ... 声明
【解决方案3】:

正如@vptheron 回答的那样,列表的头部似乎是最好的,因为你没有一个好的起始值。

但是,与其使用尾递归函数...

def getBestScore(scores: List[A]): A = {
  def go(as: List[A], acc: A): A = as match {
    case x :: xs => go(xs, getBest(acc, x)) // getBest: ((A, A) => A)
    case Nil => acc
 }
 go(scores, scores.head)
}

...您可以使用foldLeft 使其简洁。

val best = scores.foldLeft(scores.head)(getBest)

例子:

scala> def getBest(x: Int, y: Int) = if(x > y) x else y
getBest: (x: Int, y: Int)Int

scala> val scores = List(1, 20, 3)
scores: List[Int] = List(1, 20, 3)

scala> scores.foldLeft(scores.head)(getBest)
res6: Int = 20

【讨论】:

  • 请记住,其中一项要求是让算法同时产生高分者它的分数。当然,如果可以安全地假设得分并不昂贵,您可以在找到高分后重新计算它。
  • @AmigoNico,我想如果生成分数会很昂贵(不太可能:如果列表很长,无论如何它只是总时间的一小部分),总是可以用分数压缩然后对结果做 foldLeft 吧?这似乎是一个很好的答案。
  • --> 或映射到 (element, score) 然后 foldLeft 。 +1 让我跳出框框思考 :) 这就是我在使用 Scala 时遇到的问题:做事的方式总是很多。
  • 听起来你进展不错,赫尔曼!顺便说一句,在某些应用程序中,产生分数涉及对数据库的访问——因此我的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
  • 2019-01-11
相关资源
最近更新 更多