我试图找到整数列表的最小值,当它可以为空时。
scala> val minValue:Int = List() match {
| case Nil => -1
| case xs => xs.min
| }
<console>:9: error: diverging implicit expansion for type Ordering[B]
starting with method Tuple9 in object Ordering
case xs => xs.min
虽然它运作良好而非非空列表。
scala> val minValue = List(1,2) match {
| case Nil => -1
| case xs => xs.min
| }
minValue: Int = 1
如何通过排序找到min,我认为是排序并且使用getOrElse defaultValue。
答案 0 :(得分:3)
问题是类型检查器不知道List()
使用什么类型。如果您使用类型专门注释空列表,它应该可以正常工作:
val minValue:Int = List.empty[Int] match { // ...
与@senia讨论后,我意识到你可能使用-1作为“黑客”来说“没有最低限度”而不是实际价值。如果是这种情况,那么在Scala中使用Option
类型可能会更清楚,因为您可以返回实际结果的Some
变体和空列表中的None
变体。 Scala序列实际上已经为你做了一个很好的方法:
scala> List.empty[Int].reduceLeftOption(_ min _)
res0: Option[Int] = None
scala> List(5, 2, 1, 3, 4).reduceLeftOption(_ min _)
res1: Option[Int] = Some(1)
答案 1 :(得分:1)
您的实施是正确的,但您的测试用例不正确:您使用的是List[Nothing]
而不是List[Int]
,请尝试以下操作:
List[Int]() match {
case Nil => -1;
case xs => xs.min;
}
// -1
您可以为所有集合添加安全方法:
import scala.collection.GenTraversableOnce
implicit class MinMaxOpt[T](val l: GenTraversableOnce[T]) extends AnyVal {
def minOpt(implicit o: Ordering[T]) = if (l.isEmpty) None else Some(l.min)
def minOrElse[T2 >: T](default: T2)(implicit o: Ordering[T]) = minOpt getOrElse default
def maxOpt(implicit o: Ordering[T]) = if (l.isEmpty) None else Some(l.max)
def maxOrElse[T2 >: T](default: T2)(implicit o: Ordering[T]) = maxOpt getOrElse default
}
List(1, 2).minOpt
// Some(1)
List[Int]().minOrElse(-1)
// -1
答案 2 :(得分:0)
在ScalaDoc中查看List.min
的完整签名。
def min[B >: A](implicit cmp: Ordering[B]): A
你看,如果你使用List()
没有任何类型提示,它将变成List[Nothing]
类型,那么编译器找不到在cmp
的位置使用的内容,必须是类型Ordering[B]
其中B >: Nothing
(B
是Nothing
的超类型。此类型太多, - Nothing
是其他所有类型的子类型 - 所以它无法决定使用什么。)