Scala函数使用泛型函数的映射对Seq进行排序

sca*_*bie 5 sorting mapping scala

我正在尝试编写一个函数,用函数F映射序列S(我称之为F(S)),用S将结果值(F(S))拉开,然后用F(S)对结果进行排序),返回排序的压缩值(我希望代码清除它,很难放入文本)

这是我目前的代码:

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

Scalac抱怨说:

error: diverging implicit expansion for type scala.math.Ordering[M]
starting with method comparatorToOrdering in trait LowPriorityOrderingImplicits
s.map(mapper).zip(s).sortBy(_._1)

                               ^
Run Code Online (Sandbox Code Playgroud)

我会对可能出错的一些指点表示赞赏......

Tra*_*own 6

Ordering是一个类型类,这意味着如果你想捕获A以特定方式排序的事实,你只需将一个隐式实例Ordering[A]放入范围 - 你没有A扩展Ordering[A](或Ordering[AnyVal]等).

这种方法的优点是您可以处理特定类型的多个排序(尽管一种类型的一次只能有一个隐式排序).例如,我可以编写以下内容:

scala> List(5, 2, 3, 1, 4).sorted
res0: List[Int] = List(1, 2, 3, 4, 5)
Run Code Online (Sandbox Code Playgroud)

这里使用整数(Ordering.Int)的隐式排序作为隐式参数sorted,但我们也可以显式传递不同的顺序Ordering.例如,我们可以通过反转隐式排序来创建新的排序:

scala> List(5, 2, 3, 1, 4).sorted(Ordering.Int.reverse)
res1: List[Int] = List(5, 4, 3, 2, 1)
Run Code Online (Sandbox Code Playgroud)

在你的情况下sortBy正在寻找一个Ordering[Ordering[AnyVal]]不存在的.您可以通过使用上下文绑定来指示您需要订购M而不是M扩展来轻松解决此问题Ordering[AnyVal]:

def sortByZipped[S, M: Ordering](s: Seq[S], mapper: S => M): Seq[(M, S)] =
  s.map(mapper).zip(s).sortBy(_._1)
Run Code Online (Sandbox Code Playgroud)

或者你可以跳过语法糖并使用隐式参数:

def sortByZipped[S, M](s: Seq[S], mapper: S => M)(implicit o: Ordering[M]) =
  s.map(mapper).zip(s).sortBy(_._1)(o)
Run Code Online (Sandbox Code Playgroud)

这完全等同于具有上下文绑定的版本.