Scala 排序和排序以及比较选项
鉴于: 并努力做到:Scala 排序和排序以及比较选项,scala,Scala,鉴于: 并努力做到: case class Person(name: String) 导致对订单缺失的投诉 scala> List(Person("Tom"), Person("Bob")).sorted 工作正常: case class Person(name: String) extends Ordered[Person] { def compare(that: Person) = this.name compare that.name } 虽然不涉及订购或暗示 问题1:这里
case class Person(name: String)
导致对订单缺失的投诉
scala> List(Person("Tom"), Person("Bob")).sorted
工作正常:
case class Person(name: String) extends Ordered[Person] {
def compare(that: Person) = this.name compare that.name }
虽然不涉及订购或暗示
问题1:这里发生了什么?(我的钱花在了一些隐含的东西上……)
然而,鉴于上述情况以及以下事实:
scala> List(Person("Tom"), Person("Bob")).sorted
res12: List[Person] = List(Person(Bob), Person(Tom))
res13: List[Option[Int]] = List(None, Some(1), Some(2))
有效,而且:
scala> Person("Tom") > Person("Bob")
res15: Boolean = true
开箱即用:
scala> List(Some(2), None, Some(1)).sorted
我希望:
scala> List(Person("Tom"), Person("Bob")).sorted
res12: List[Person] = List(Person(Bob), Person(Tom))
res13: List[Option[Int]] = List(None, Some(1), Some(2))
也会起作用,但它不会:
scala> Some(2) > Some(1)
:6:error:value>不是某些[Int]的成员
一些(2)>一些(1)
问题#2:为什么不,我如何才能让它工作?列表的
排序方法的定义是:
<console>:6: error: value > is not a member of Some[Int]
Some(2) > Some(1)
是的,隐式的事情正在发生,但是标准库中的许多类都有与它们关联的隐式对象,而不必首先导入它们
伴随对象定义了一组隐式排序。其中包括OptionOrdering和IntOrdering,这有助于解释列表调用sorted
的能力
要在存在隐式转换时使用运算符,需要导入该对象,例如:
def sorted [B >: A] (implicit ord: Ordering[B]): List[A]
def cmpSome(l:Option[Int],r:Option[Int])(隐式order:Ordering[Option[Int]])={
进口订单_
lcmpSome(一些(0),一些(1))
res2:Boolean=true
关于您的第一个问题:有序[T]
扩展了可比[T]
。排序
伴随对象为任何可以转换为可比[T]
的值提供隐式的排序[T]
:
def cmpSome(l:Option[Int], r:Option[Int])(implicit ord:Ordering[Option[Int]]) = {
import ord._
l < r
}
scala> cmpSome(Some(0), Some(1))
res2: Boolean = true
implicit def ordered[A]
-这就是为什么Some(1)>Some(2)
不起作用的原因
如果定义这样的转换是一个好主意,那就值得怀疑了,因为最终可能会将对象包装成
有序的
实例,然后再次创建有序的
(依此类推……)。更糟糕的是:您可以在范围内创建两个具有不同排序的实例的排序
实例,这当然不是您想要的。如果您安装的默认范围有点太神奇,您可以比较如下选项:
implicit def ordered[A <% Comparable[A]]: Ordering[A]
scala>导入scala.math.Ordering.Implicits_
导入scala.math.Ordering.Implicits_
scala>def-cmpSome[T:Ordering](x:Option[T],y:Option[T])=x
导入为您提供了一个从排序到类的隐式的中缀操作,这样就足够在不进行另一次导入的情况下进行排序了。我假设您理解为什么在未传递排序且范围中没有可用的排序时,排序不起作用。
至于为什么从Ordered trait扩展类时,排序函数会起作用。答案是,从Ordered trait扩展类时,代码类型会检查trait是否包含类似etc的函数。因此不需要进行隐式转换,因此不会抱怨缺少隐式排序
scala> List(Person("Tom"), Person("Bob")).sorted
至于你的第二个问题,Some(2)>Some(1)
将不起作用,因为有些不扩展所排序的特征,范围中似乎也没有任何隐式函数隐式地将Some转换为具有函数
的东西来回答你的第二个问题,为什么你不能这样做:Some(2)>Some(1)
您可以通过导入并使用选项[Int]
而不是某些[Int]
scala> import scala.math.Ordering.Implicits._
import scala.math.Ordering.Implicits._
scala> def cmpSome[T: Ordering](x: Option[T], y: Option[T]) = x < y
cmpSome: [T](x: Option[T], y: Option[T])(implicit evidence$1: Ordering[T])Boolean
实际上,您的类型可能是选项[Int]
,而不是某些[Int]
,因此它不会那么难看,您也不需要显式的向上转换。感谢您提供了一个带有示例的详细问题
我的答案是根据我从一篇伟大的文章中学到的:
这一切都归功于作者
引述该条:
回到我们的方框示例——scala库定义了有序[T]和有序[T]之间的隐式转换,反之亦然。
中的Ordered
的伴随对象在此处提供所需的转换:
/**镜头从'Ordering[T]`到'Ordering[T]`*/
隐式定义排序有序[T](x:T)(隐式ord:Ordering[T]):有序[T]=
新排序的[T]{def compare(that:T):Int=ord.compare(x,that)}
但是,反向转换没有定义,我也不知道为什么?这并不能真正回答为什么实现有序[t]会神奇地产生一个有序[t]的实例的问题。为什么要创建一个方法来进行最后一次比较?我创建了该方法,以便能够访问Ordering实例。我导入该实例的内容,以便将其隐式转换为Ops
,后者定义了一些比较运算符。使用相同的方法,我最终确定了对一个有序的进行隐式转换是可行的。但是,仅仅为了能够比较两个选项,这似乎是相当多的工作?导入ord.\u
正是我想要的更好…但在我看来,仍然有很多工作,也许不是那么简单。:)我理解这种方式可能有原因,但从用户的角度来看,比较两个选项似乎是合乎逻辑的,因为你可以在没有任何模糊的情况下对它们的列表进行排序…因为你必须在另一个中进行比较才能进行排序,对吗?你可以对它们进行排序,因为你调用了一个采用隐式顺序的方法ng.这里您正在编写一个采用隐式排序的方法。在某个地方,排序必须输入图片,因为任意选项[T]是不可比较的。