Inspirado en respuesta Ben Lings', escribí mi propia versión de sort
:
def sort[A : Ordering](coll: Seq[Iterable[A]]) = coll.sorted
lo que equivale a:
def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
Tenga en cuenta que ordering
se convierte implícitamente a Ordering[Iterable[A]]
.
Ejemplos:
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))
Se preguntó cómo proporcionar su propia función de comparación; Basta con utilizar 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
le permite asignar su valor en otro tipo para el cual ya existe una instancia de pedido. Dado que también se ordenan las tuplas, esto puede ser útil para la comparación lexicográfica de clases de casos.
para hacer un ejemplo, vamos a definir una envoltura de un Int, aplicar Ordering.by(_.v)
, donde _.v
extrae el valor subyacente, y muestran que se obtiene el mismo resultado:
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)))
Por último, vamos a hacer lo mismo en caso de una clase con más miembros, reutilizando los comparadores de tuplas:
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)))
Personalmente, prefiero usar un algoritmo recursivo, que puede estar hecho recursiva de cola para este problema en particular. –
@Daniel, ¿podría explicar brevemente por qué prefiere usar un algoritmo recursivo? –
Las listas conducen a algoritmos recursivos con bastante facilidad, por lo que estoy acostumbrado a pensar en la recursión con ellos. Y, en este caso, creo que sería más limpio. Aún así, es puramente una cuestión de gusto y estilo. –