max()应该为空列表返回什么?

时间:2014-04-25 16:29:31

标签: scala

得到java.util.NoSuchElementException: head of empty list所以我试着检查一下。但现在我得到了[info] - max of a few numbers *** FAILED *** [info] 0 did not equal 7 (ListsSuite.scala:128)

def max(xs: List[Int]): Int = {
  if xs.isEmpty 0 // What can I do? 
  else if (xs.head > max(xs.tail)) max(xs.tail)
  else max(xs.tail)
}

编辑:

  1. 测试用例失败,因为我的测试错了。
  2. 对于我的class队友,提醒一下Coursera荣誉代码:

    • 我只会注册一个帐户。我回答家庭作业,测验 考试将是我自己的工作(明确的作业除外) 允许合作)。
    • 我不会为家庭作业,测验做出解决方案 或者其他任何人都可以参加考试。这包括两种解决方案 我写的,以及由我提供的任何官方解决方案 课程人员。
    • 我不会从事任何其他活动 不诚实地改善我的结果或不诚实地改善/伤害 别人的结果。

3 个答案:

答案 0 :(得分:2)

在一般情况下,除了None之外,您不能返回任何内容,因为一般来说空序列没有有意义的默认最大值。然而,这并不一定是这种情况;例如,您可能希望在人员列表中找到最高薪水,在这种情况下,如果列表为空,则说它为0是有意义的;但是,通常没有简单的方法来实现这样的默认值逻辑(你必须使用类型类和包装值之类的东西);现在最好的选择就是使用Option[Int]

def max(xs: List[Int]): Option[Int] = xs match {
  case Nil => None
  case x :: Nil => Some(x)
  case x :: xs => Some(x max max(xs))
}

然后,您可以轻松地回到呼叫站点的默认值:

val posOrNeg = List(-5, -2, 1, 4, 10)
max(posOrNeg) // => Some(10)
val posOrNeg = List.empty[Int]
max(posOrNeg) // => None

val onlyPos = List(1, 2, 3)
max(onlyPos).getOrElse(0) // => 3
val onlyPos = List.empty[Int]
max(onlyPos).getOrElse(0) // => 0

加分:此外,您可以让max处理任何数值列表:

def max[T: Numeric](xs: List[T]): Option[T] = xs match {
  case Nil => None
  case x :: Nil => Some(x)
  case x :: xs => Some(x max max(xs))
}

或者实际上任何合适的数据结构都是使用比List更通用的类型由数值组成的,但我会留给您。

但请记住:无论您选择哪种解决方案,总是尽量避免try和异常 - 异常不符合惯用函数编程的精神(即使甚至一些库函数偶尔会出于各种原因使用它们。)

答案 1 :(得分:0)

我选择选项

def max(xs: List[Int]) = 
  if xs.isEmpty None
  else if (xs.head > max(xs.tail)) Some( max(xs.tail) )
  else Some( max(xs.tail))

Option-Monad可以是 Some(result),意味着有结果或 None ,这意味着没有结果。如果你在 Some 中包装一些东西,你说它是结果,一切都很好。

作为替代解决方案,您可以将所有内容包装在尝试中,这将是最好的,因为空列表没有最大值,并且正确的方法是获取错误但是现在你可以以功能的方式处理它。

def max(xs: List[Int]) = Try( if (xs.head > max(xs.tail)) max(xs.tail) else xs.tail )

答案 2 :(得分:-1)

为空集合定义max元素没有意义,所以你应该返回一个sentinel值,或抛出异常(例如IllegalArgumentException)。

此外,您应该对代码进行一些更改(如果您想自己实现它,而不是使用内置的东西):

def max(list: List[Int]): Option[Int] = {
    list match {
        // List has no elements, so we return None
        case Nil => None
        // Only one element, that is the maximum
        case x :: Nil => Some(x)
        // Compute max(list.tail). 
        // If defined, it will return the greater of list.tail and list.head
        case head :: tail => max(tail).map(_ max head)
    }
}