Scala 按类型对案例 类 进行排序
Scala sorting of case classes by type
鉴于某些情况 类 扩展了一个共同特征,我希望能够根据它们的类型定义一个排序(实际上不一定,目标是以这种方式对它们进行排序)。例如:
sealed trait Element
case class A(x: Int) extends Element
case class B(x: Int) extends Element
case class C(x: Int) extends Element
case class D(x: Int) extends Element
case class E(x: Int) extends Element
case class F(x: Int) extends Element
val elements: List[Element] = List(
A(5), F(3), E(1), C(19), A(3), F(1)
)
排序为 F -> A -> all other cases
,结果列表为 List(F(3), F(1), A(5), A(3), E(1), C(19))
。相同类型的元素之间的顺序无关紧要。
我想出了多种不同的解决方案,但它们看起来都很复杂,我只是觉得我缺少一些明显的方法来实现这一点。这就是我使用排序实现它的方式:
val sorted = elements.sorted{(a: Element, b: Element) => (a, b) match {
case (_: F, _: F) => 0
case (_: F, _ ) => -1
case (_ , _: F) => 1
case (_: A, _: A) => 0
case (_: A, _ ) => -1
case (_ , _: A) => 1
case _ => 0
}
}
然而,这显然会非常可怕,而且看起来也不好..
引入一个class怎么样,它会优先排序元素,例如:
class Prio(val prio: Int) {}
case class A() extends Prio(5)
case class B() extends Prio(3)
case class C() extends Prio(9)
case class D() extends Prio(7)
object Prio {
def main(args: Array[String]): Unit = {
List(A(), B(), C(), D())
.sortBy(_.prio)
.foreach(println)
}
}
结果如下:
B()
A()
D()
C()
你当然可以混入其他接口,为类型class添加值。 Prio
class 甚至可以丰富更多的优先级,可以在不同的情况下使用。
因为您只想让 A
在前,F
在后,您可以使用以下顺序:
class Prio(val prio: Int) {}
case class A() extends Prio(-1)
case class B() extends Prio(0)
case class C() extends Prio(0)
case class D() extends Prio(0)
case class E() extends Prio(0)
case class F() extends Prio(1)
只需为 Element
定义一个 implicit
Ordering
,如下所示:
object Element {
implicit val ord: Ordering[Element] = Ordering.by {
case _: F => 0
case _: A => 1
case _ => 2
}
}
那么elements.sorted
会给你想要的答案
鉴于某些情况 类 扩展了一个共同特征,我希望能够根据它们的类型定义一个排序(实际上不一定,目标是以这种方式对它们进行排序)。例如:
sealed trait Element
case class A(x: Int) extends Element
case class B(x: Int) extends Element
case class C(x: Int) extends Element
case class D(x: Int) extends Element
case class E(x: Int) extends Element
case class F(x: Int) extends Element
val elements: List[Element] = List(
A(5), F(3), E(1), C(19), A(3), F(1)
)
排序为 F -> A -> all other cases
,结果列表为 List(F(3), F(1), A(5), A(3), E(1), C(19))
。相同类型的元素之间的顺序无关紧要。
我想出了多种不同的解决方案,但它们看起来都很复杂,我只是觉得我缺少一些明显的方法来实现这一点。这就是我使用排序实现它的方式:
val sorted = elements.sorted{(a: Element, b: Element) => (a, b) match {
case (_: F, _: F) => 0
case (_: F, _ ) => -1
case (_ , _: F) => 1
case (_: A, _: A) => 0
case (_: A, _ ) => -1
case (_ , _: A) => 1
case _ => 0
}
}
然而,这显然会非常可怕,而且看起来也不好..
引入一个class怎么样,它会优先排序元素,例如:
class Prio(val prio: Int) {}
case class A() extends Prio(5)
case class B() extends Prio(3)
case class C() extends Prio(9)
case class D() extends Prio(7)
object Prio {
def main(args: Array[String]): Unit = {
List(A(), B(), C(), D())
.sortBy(_.prio)
.foreach(println)
}
}
结果如下:
B()
A()
D()
C()
你当然可以混入其他接口,为类型class添加值。 Prio
class 甚至可以丰富更多的优先级,可以在不同的情况下使用。
因为您只想让 A
在前,F
在后,您可以使用以下顺序:
class Prio(val prio: Int) {}
case class A() extends Prio(-1)
case class B() extends Prio(0)
case class C() extends Prio(0)
case class D() extends Prio(0)
case class E() extends Prio(0)
case class F() extends Prio(1)
只需为 Element
定义一个 implicit
Ordering
,如下所示:
object Element {
implicit val ord: Ordering[Element] = Ordering.by {
case _: F => 0
case _: A => 1
case _ => 2
}
}
那么elements.sorted
会给你想要的答案