Скажем, у меня есть набор строк, которые я хочу упорядочить по длине, но уникальных по обычной String
уникальности. Я имею в виду, что у меня может быть несколько строк одинаковой длины в Set
, но они должны быть отсортированы по длине.
Я хочу выразить заказ следующим образом:
val orderByLength = Ordering[Int].on[String](_ length)
который, я думаю, выглядит действительно красиво. Но если бы я бросил это в SortedSet, скажи так:
scala> val s = SortedSet("foo", "bar")(orderByLength)
s: scala.collection.immutable.SortedSet[java.lang.String] = TreeSet(bar)
Я получаю только «бар». Это потому, что 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)
}
Что я могу использовать как:
val ordering = Ordering[Int].on[String](_ length) ifEqual Ordering[String]
Я думал, что это выглядело действительно великолепно, но потом я понял, что то, что я хотел сделать, это не просто упорядочивать по естественному упорядочению строк, я просто хотел упорядочить по размеру, но уникальность по другому. Возможно ли это более элегантным способом?