我已经定义了以下Seq的隐式充实
class OrderedSeqEnricher[T <% Ordered[T]](seq: Seq[T]) {
def binarySearch(e: T): Int = binarySearch(e, 0, seq.length)
private def binarySearch(e: T, start: Int, end: Int): Int =
if (start < end) {
val mid = start + (end - start) / 2
if (e < seq(mid)) binarySearch(e, start, mid)
else if (e > seq(mid)) binarySearch(e, mid + 1, end)
else mid
}
else -start
}
implicit def toOrderedSeqEnricher[T <% Ordered[T]](seq: Seq[T]) = new OrderedSeqEnricher(seq)
我遇到的问题是,在某些情况下,我想使用seq来存储ID,这些ID用于查找树中的对象,然后比较这些对象。像这样:
implicit def ordering: Ordering[Int] = (i1: Int, i2: Int) =>
if (tree(i1).myCompare(tree(i2)) < 0) -1 else 1
有没有一种方法可以明确指定这是要使用的顺序,而不是将它们视为简单的整数?
答案 0 :(得分:2)
您可以将一个类和一个implicit def
组合在一起,而该类只需使用implicit class
进行构造即可:
implicit class OrderedSeqEnricher[T <% Ordered[T]](seq: Seq[T]) { ... }
引用Ordered
文档:
具有单一自然顺序的数据的特征。有关是否使用scala.math.Ordering的更多信息,请参阅使用此特征之前的scala.math.Ordering。
因此您不能将Ordering
与<% Ordered[T]
一起使用。相反,更喜欢: Ordering
(除非您有一些非常具体的理由使用Ordered
,否则我通常会这样做):
implicit class OrderedSeqEnricher[T : Ordering](seq: Seq[T]) { ... }
然后,您可以将
明确传递给ordering
new OrderedSeqEnricher(someIntSeq)(ordering).binarySearch(...)
或者将参数而不是类放在方法上:
implicit class OrderedSeqEnricher[T](seq: Seq[T]) {
def binarySearch(e: T)(implicit ordering: Ordering[T]): Int = binarySearch(e, 0, seq.length)
private def binarySearch(e: T, start: Int, end: Int)(implicit ordering: Ordering[T]): Int =
if (start < end) {
val mid = start + (end - start) / 2
if (e < seq(mid)) binarySearch(e, start, mid)
else if (e > seq(mid)) binarySearch(e, mid + 1, end)
else mid
}
else -start
}
someIntSeq.binarySearch(...)(ordering)
另一个可能的好主意是使id与Int
s成为一个单独的值类(以防止对id无意义的任何运算,例如算术运算):
class Id(value: Int) extends AnyVal { ... }
object Id {
implicit def ordering(implicit tree: Tree): Ordering[Id] = (i1: Id, i2: Id) =>
// assumes trees are changed to apply(Id) instead of apply(Int)
if (tree(i1).myCompare(tree(i2)) < 0) -1 else 1
}