Scala SortedSet - 按一个排序和其他东西排序?

Vik*_*alk 9 scala scala-collections

假设我有一组字符串,我希望按长度排序,但通过正常的String唯一性进行排序.我的意思是我可以拥有多个相同长度的字符串Set,但是它们应该按长度排序.

我想表达这样的顺序:

val orderByLength = Ordering[Int].on[String](_ length)
Run Code Online (Sandbox Code Playgroud)

我觉得看起来很不错.但如果我把它扔进SortedSet,就像这样说:

scala> val s = SortedSet("foo", "bar")(orderByLength)
s: scala.collection.immutable.SortedSet[java.lang.String] = TreeSet(bar)
Run Code Online (Sandbox Code Playgroud)

我只得到'酒吧'.这是因为它Ordering表示总排序,因此当compare返回0时,元素被认为是相同的.

因此,我认为如果长度相等,我需要进行链式排序并比较字符串.为此,我使用了"pimp my library" - 这样的模式:

trait ChainableOrderings {
  class ChainableOrdering[T](val outer: Ordering[T]) {
    def ifEqual(next: Ordering[T]): Ordering[T] = new Ordering[T] {
      def compare(t1: T, t2: T) = {
        val first = outer.compare(t1, t2)
        if (first != 0) first else next.compare(t1, t2)
      }
    }
  }
  implicit def chainOrdering[T](o: Ordering[T]) = new ChainableOrdering[T](o)
}
Run Code Online (Sandbox Code Playgroud)

我可以使用像:

val ordering = Ordering[Int].on[String](_ length) ifEqual Ordering[String]
Run Code Online (Sandbox Code Playgroud)

我觉得它看起来真的很棒,但后来我意识到我想要做的并不是按照字符串的自然顺序排序,我只是想按尺寸排序,而是通过别的东西来排序.这可能是一种更优雅的方式吗?

Dan*_*ral 18

我在这种情况下做的是这样的:

val orderByLength = Ordering[(Int, String)].on[String](s => s.length -> s)
Run Code Online (Sandbox Code Playgroud)

换句话说,使用元组来获得打破平局.

另一方面,我认为SortedSet基于它们的排序来考虑元素是愚蠢的.我认为之前已经讨论过这个问题,但是我不会放弃搜索邮件列表档案和scala trac的讨论/票据的可能性,也许还会尝试SortedSet改变它的行为.

  • 集合仅包含不同的对象.有序集合具有总排序.特别是,`S包含a`和`S包含b`意味着'a <b`或`b <a`或`a eq b`.你是否建议`SortedSet`有某种部分排序(例如等价类而不是项目的总排序)? (4认同)