5 Stimmen

Scala-Funktion, die eine Seq mithilfe der Abbildung einer generischen Funktion sortiert

Ich versuche, eine Funktion zu schreiben, die eine Sequenz S mit einer Funktion F abbildet (die ich F(S) nenne), die die resultierenden Werte (F(S)) mit S zippt und das Ergebnis nach F(S) sortiert, um die sortierten gezippten Werte zurückzugeben (Ich hoffe, der Code klärt das auf, es ist schwer in Textform zu erklären)

Hier ist mein aktueller Code:

def sortByAndReturnZippedMetric[S,M<:Ordering[AnyVal]]( s:Seq[S], mapper:S=>M):Seq[(M,S)] =
s.map(mapper).zip(s).sortBy(_._1)

Scalac beschwert sich jedoch:

Fehler: abweichende implizite Erweiterung für Typ scala.math.Ordering[M]
beginnend mit der Methode comparatorToOrdering im Trait LowPriorityOrderingImplicits
s.map(mapper).zip(s).sortBy(_._1)

                               ^

Ich würde mich über Hinweise dazu freuen, was möglicherweise falsch sein könnte...

6voto

Travis Brown Punkte 137441

Ordnung ist ein Typklasse, was bedeutet, dass wenn du erfassen möchtest, dass A auf eine bestimmte Weise geordnet ist, setzt du einfach eine implizite Instanz von Ordnung[A] in den Scope - du lässt A also nicht Ordnung[A] (oder Ordnung[AnyVal] usw.) erweitern.

Der Vorteil dieser Vorgehensweise ist, dass du mit mehreren Ordnungen für einen bestimmten Typ arbeiten kannst (obwohl nur eine implizite Ordnung gleichzeitig für einen Typ im Scope sein kann). So kann ich zum Beispiel folgendes schreiben:

scala> List(5, 2, 3, 1, 4).sorted
res0: List[Int] = List(1, 2, 3, 4, 5)

Hier wird die implizite Ordnung für Ganzzahlen (Ordnung.Int) als implizites Argument an sortiert übergeben, aber wir könnten auch explizit eine andere Ordnung übergeben. Zum Beispiel könnten wir eine neue Ordnung erstellen, indem wir die implizite umkehren:

scala> List(5, 2, 3, 1, 4).sorted(Ordnung.Int.umkehren)
res1: List[Int] = List(5, 4, 3, 2, 1)

In deinem Fall sucht sortiereNach nach einer Ordnung[Ordnung[AnyVal]], die es nicht gibt. Du kannst das leicht beheben, indem du eine Kontextbindung verwendest, um anzuzeigen, dass du eine Ordnung für M benötigst, anstatt M auf Ordnung[AnyVal] erweitern zu lassen:

def sortByZipped[S, M: Ordnung](s: Seq[S], mapper: S => M): Seq[(M, S)] =
  s.map(mapper).zip(s).sortBy(_._1)

Oder du kannst den syntaktischen Zucker überspringen und ein implizites Argument verwenden:

def sortByZipped[S, M](s: Seq[S], mapper: S => M)(implicit o: Ordnung[M]) =
  s.map(mapper).zip(s).sortBy(_._1)(o)

Dies entspricht genau der Version mit der Kontextbindung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X