我正在尝试编写一个函数,该函数通过函数F映射序列S(我称其为F(S)),将结果值(F(S))压缩为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)
但是,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)
^
对于可能出了什么问题,我将不胜感激。
最佳答案
Ordering
是type class,这意味着,如果要捕获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)
这里,整数的隐式排序(
Ordering.Int
)被用作sorted
的隐式参数,但我们也可以显式地传递不同的Ordering
。例如,我们可以通过反转隐式的顺序来创建新的顺序:scala> List(5, 2, 3, 1, 4).sorted(Ordering.Int.reverse)
res1: List[Int] = List(5, 4, 3, 2, 1)
在您的情况下,
sortBy
正在寻找Ordering[Ordering[AnyVal]]
,它不存在。您可以使用context bound来指示需要对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)
或者,您可以跳过语法糖并使用隐式参数:
def sortByZipped[S, M](s: Seq[S], mapper: S => M)(implicit o: Ordering[M]) =
s.map(mapper).zip(s).sortBy(_._1)(o)
这完全等同于具有上下文绑定(bind)的版本。
关于使用通用函数的映射对Seq排序的Scala函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13555891/