加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala成语通过多个标准排序

发布时间:2020-12-16 09:33:40 所属栏目:安全 来源:网络整理
导读:我想做这样的事情: class Foo extends Ordered[Foo] { val x val y val z . . . . def compare(that: Foo) = { val c0 = this.length compareTo that.length // primary comparison lazy val c1 = this.x compareTo that.x // secondary comparison lazy va
我想做这样的事情:

class Foo extends Ordered[Foo] {
   val x
   val y
   val z
   .
   .
   .
   .
   def compare(that: Foo) = {
      val c0 = this.length compareTo that.length          // primary comparison
      lazy val c1 = this.x compareTo that.x               // secondary comparison
      lazy val c2 = this.y.size compareTo that.y.size     // tertiary comparison
      lazy val c3 = this.z.head compareTo that.z.head     // final tie breaker
      if (c0 != 0) c0 else if (c1 != 0) c1 else if (c2 != 0) c2 else if (c3 != 0) c3 else c4
   }    
}

我想知道是否有更清洁的方式来写这样的事情。我期待有一些像Ordering.multipleBy(排序:有序的[A] *)签名,它采用可比较的变量,并选择第一个非零。

解决方法

使用Ordering而不是Ordered通常更好。订购是一个类型类,比订单更灵活(如果只是因为Ordered必须通过类型来实现比较,而使用Ordering可以在外部定义)。要定义类型的自然排序(默认排序实例),您只需在协同对象中定义隐式排序值。

所以,足够的序言。好的是,当使用Ordering你想做的是很简单的,因为元组的隐含排序(假设元组元素本身有一个顺序)`:

object Foo {
  implicit val FooOrdering = Ordering.by{ foo: Foo => 
    (foo.length,foo.x,foo.y,foo.z) 
  }
}

此外,还有一个隐式转换,它将具有Ordering类型类实例的任何值转换为Ordered值(请参阅Ordered.orderingToOrdered),因此我们没有任何特别要求可以将Foo的任何实例传递给一个函数,期望一个有序的[Foo])

更新:关于你的新问题:

Slightly related – is there any way to compose orderings?

一种方法是使用大部分基于Ordering.by和转换为元组的相同技术,但明确地将订单传递给组合:

val byXOrdering = Ordering.by{ foo: Foo => foo.x }
val byYOrdering = Ordering.by{ foo: Foo => foo.y }
val byZOrdering = Ordering.by{ foo: Foo => foo.z }

// Compose byXOrdering and byYOrdering:
val byXThenYOrdering = Ordering.by{ foo: Foo => (foo,foo) }(Ordering.Tuple2(byXOrdering,byYOrdering))

// Compose byXOrdering and byYOrdering and byZOrdering:
val byXThenYThenZOrdering = Ordering.by{ foo: Foo => (foo,foo,foo) }(Ordering.Tuple3(byXOrdering,byYOrdering,byZOrdering))

但这是相对“嘈杂”的。
我找不到任何更好的只使用标准库,所以我实际上建议使用我们自己的帮助:

final class CompositeOrdering[T]( val ord1: Ordering[T],val ord2: Ordering[T] ) extends Ordering[T] {
  def compare( x: T,y: T ) = {
    val comp = ord1.compare( x,y )
    if ( comp != 0 ) comp else ord2.compare( x,y )
  }
}
object CompositeOrdering {
  def apply[T]( orderings: Ordering[T] * ) = orderings reduceLeft (_ orElse _)
}
implicit class OrderingOps[T]( val ord: Ordering[T] ) extends AnyVal {
  def orElse( ord2: Ordering[T] ) = new CompositeOrdering[T]( ord,ord2 )
}

可以这样使用:

val byXOrdering = Ordering.by{ foo: Foo => foo.x }
val byYOrdering = Ordering.by{ foo: Foo => foo.y }
val byZOrdering = Ordering.by{ foo: Foo => foo.z }

// Compose byXOrdering and byYOrdering:
val byXThenYOrdering = byXOrdering orElse byYOrdering

// Compose byXOrdering and byYOrdering and byZOrdering:
val byXThenYThenZOrdering = byXOrdering orElse byYOrdering orElse byZOrdering

或者更简单,就像这样:

// Compose byXOrdering and byYOrdering:
val byXThenYOrdering = CompositeOrdering(byXOrdering,byYOrdering)

// Compose byXOrdering and byYOrdering and byZOrdering:
val byXThenYThenZOrdering = CompositeOrdering(byXOrdering,byZOrdering)

CompositeOrdering.apply基本上是你所说的Ordering.multipleBy在你的问题。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读