Вдохновленный ответ Бен Лингс, я написал свою собственную версию sort
:
def sort[A : Ordering](coll: Seq[Iterable[A]]) = coll.sorted
что эквивалентно:
def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
Обратите внимание, что ordering
неявно преобразуется в Ordering[Iterable[A]]
.
Примеры:
scala> def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
sort: [A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A])Seq[Iterable[A]]
scala> val coll = List(List(1, 3), List(1, 2), List(0), Nil, List(2))
coll: List[List[Int]] = List(List(1, 3), List(1, 2), List(0), List(), List(2))
scala> sort(coll)
res1: Seq[Iterable[Int]] = List(List(), List(0), List(1, 2), List(1, 3), List(2))
был задан вопрос о том, как поставить свою функцию сравнения; Достаточно использовать Ordering.fromLessThan:
scala> sort(coll)(Ordering.fromLessThan(_ > _))
res4: Seq[Iterable[Int]] = List(List(), List(2), List(1, 3), List(1, 2), List(0))
Ordering.by
позволяет сопоставить значение в другой тип, для которого существует уже экземпляр заказа. Учитывая, что и кортежи упорядочены, это может быть полезно для лексикографического сравнения классов случаев.
Для примера, давайте определим обертку с Int, применяются Ordering.by(_.v)
, где _.v
извлекает основную ценность, и показать, что мы получаем тот же результат:
scala> case class Wrap(v: Int)
defined class Wrap
scala> val coll2 = coll.map(_.map(Wrap(_)))
coll2: List[List[Wrap]] = List(List(Wrap(1), Wrap(3)), List(Wrap(1), Wrap(2)), List(Wrap(0)), List(), List(Wrap(2)))
scala> sort(coll2)(Ordering.by(_.v))
res6: Seq[Iterable[Wrap]] = List(List(), List(Wrap(0)), List(Wrap(1), Wrap(2)), List(Wrap(1), Wrap(3)), List(Wrap(2)))
Наконец, давайте сделаем то же самое на случай класса с большим количеством участников, повторное использование компараторов для кортежей:
scala> case class MyPair(a: Int, b: Int)
defined class MyPair
scala> val coll3 = coll.map(_.map(MyPair(_, 0)))
coll3: List[List[MyPair]] = List(List(MyPair(1,0), MyPair(3,0)), List(MyPair(1,0), MyPair(2,0)), List(MyPair(0,0)), List(), List(MyPair(2,0)))
scala> sort(coll3)(Ordering.by(x => (x.a, x.b)))
res7: Seq[Iterable[MyPair]] = List(List(), List(MyPair(0,0)), List(MyPair(1,0), MyPair(2,0)), List(MyPair(1,0), MyPair(3,0)), List(MyPair(2,0)))
Лично я предпочел бы использовать рекурсивный алгоритм, который может быть изготовлен с хвостовой рекурсией для этой конкретной проблемы. –
@ Даниэль, не могли бы вы вкратце объяснить, почему вы предпочитаете использовать рекурсивный алгоритм? –
Списки ведут себя к рекурсивным алгоритмам довольно легко, поэтому я привык думать о рекурсии с ними. И, в этом случае, я думаю, что это будет чище. Тем не менее, это чисто дело вкуса и стиля. –