Ispirato risposta Ben Lings', ho scritto la mia versione di sort
:
def sort[A : Ordering](coll: Seq[Iterable[A]]) = coll.sorted
che è equivalente a:
def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
noti che ordering
viene convertito in modo implicito Ordering[Iterable[A]]
.
Esempi:
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))
è stato chiesto come fornire la propria funzione di confronto; Basta usare 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
consente di mappare il tuo valore in un altro tipo per i quali esiste già un'istanza di ordinazione. Dato che anche le tuple sono ordinate, questo può essere utile per il confronto lessicografico delle classi di casi.
per fare un esempio, definiamo un involucro di un Int, applicare Ordering.by(_.v)
, dove _.v
estrae il valore sottostante, e mostrare che si ottiene lo stesso risultato:
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)))
Infine, cerchiamo di fare la stessa cosa su una classe case con più membri, riutilizzando i comparatori di tuple:
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, preferisce utilizzare un algoritmo ricorsivo, che può essere fatta ricorsiva in coda per questo particolare problema. –
@Daniel, potresti spiegare brevemente perché preferisci usare un algoritmo ricorsivo? –
Gli elenchi portano piuttosto facilmente ad algoritmi ricorsivi, quindi sono abituato a pensare alla ricorsione con loro. E, in questo caso, penso che sarebbe più pulito. Tuttavia, è puramente una questione di gusto e stile. –