如何定义Ordering [Array[Byte]]?

6

需要从头实现吗?我找不到匹配的隐式方法,即使在最后的“Implicits”特质中也没有。显然,“seqDerivedOrdering”不起作用,因为“Array”不是“Seq”。

3个回答

8
如果您希望它更有效率,您需要编写自己的代码(此代码处理空值,如果您可以保证没有空值,则只需使用长else块):
val o = new math.Ordering[Array[Byte]] {
  def compare(a: Array[Byte], b: Array[Byte]): Int = {
    if (a eq null) {
      if (b eq null) 0
      else -1
    }
    else if (b eq null) 1
    else {
      val L = math.min(a.length, b.length)
      var i = 0
      while (i < L) {
        if (a(i) < b(i)) return -1
        else if (b(i) < a(i)) return 1
        i += 1
      }
      if (L < b.length) -1
      else if (L < a.length) 1
      else 0
    }
  }
}

否则,您可以使用.toSeq将其打包成WrappedArray并推迟到Seq比较而不是进行自己的扫描。 (这将导致字节的装箱和拆箱,因此效率不高。由于字节装箱通常是通过查找所有字节的表来完成的,所以它并不是非常低效,因此除非您正在进行例如重型二进制文件处理之类的操作,否则可能可以获得成功。)

是的,我想添加类似的内容,但在此之前想要询问一下。也许将某些内容添加到标准库中会更加明显? - venechka
@venechka - 如果 Array 对象为每种类型实现这些功能就太好了。也许有人应该提交一个增强请求?但与此同时,标准库中确实有很多方便的东西是没有的。你应该习惯使用自己的个人标准库来填补需要的那些部分! - Rex Kerr
我认为只有一个 @specialized 版本就足够了。 - venechka
@venechka - 原则上是的。但在实践中,我遇到了很多特定问题的错误,所以直到我见到它工作才会说它可以解决问题。如果它起作用,那么它不会轻松地工作,因为您需要在基本类型上定义 < ,而 Ordering 不是专业化的,因此您不能仅仅推迟到该方法。所以你必须创建自己的特殊版本 Numeric 并从那里开始工作。 - Rex Kerr
无论如何,使用toSeq的性能惩罚似乎不会太严重。 - GClaramunt

7
如果你更注重简洁而不是原始性能:
scala> Ordering.by((_: Array[Byte]).toIterable)
res0: scala.math.Ordering[Array[Byte]] = scala.math.Ordering$$anon$7@8c9f531

2

您可以实现一个非常简单的Ordering,它在比较数组时调用toSeq,然后调用seqDerivedOrdering。将其转换为Seq应该在性能方面几乎是免费的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接