假设我有一张地图:
val m = Map("foo" -> 10, "bar" -> 5)
Run Code Online (Sandbox Code Playgroud)
我想将其转换为以下格式的字符串(键和值用":"分隔,不同的元素用","分隔):
"bar:5,foo:10"
Run Code Online (Sandbox Code Playgroud)
请注意,现在订购了密钥.
如何编写函数来执行此转换?我试过了
def f[A, B](m: Map[A, B]): String = {
m.toList.sortBy(_._1).map { x => x._1 + ":" + x._2 }.mkString(",")
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为不知何故我需要指定A可订购的.我不知道该怎么做 - 我尝试Orderer在我的函数中添加一个隐式参数,但它没有用.
使用Ordering类型类:
def f[A: Ordering, B](m: Map[A, B]): String = {
m.toList.sortBy(_._1).map { x => x._1 + ":" + x._2 }.mkString(",")
}
Run Code Online (Sandbox Code Playgroud)
这会f使用隐式Ordering参数添加另一个参数列表.方法签名实际上是在场景后面翻译的:
def f[A, B](m: Map[A, B])(implicit evidence: Ordering[A]): String
Run Code Online (Sandbox Code Playgroud)
evidence然后该参数被sortBy用于比较元素并用于比较元素.
编辑:
请注意,您不能Ordered以相同的方式使用Ordering.该Ordered特征旨在与将要排序的对象类型混合(如在Java中).换句话说,A必须扩展Ordered[A]然后你会把它写成A <: Ordered[A].
但是,这种继承方法Ordered不如类型类方法强大Ordering,因为它不太灵活.如果其他人定义A并且没有决定使其扩展Ordered[A],那么你将无法使用它sortBy(至少在没有创建包装类的情况下).另一方面,您始终可以Ordering[A]在不更改A继承内容的情况下声明新的隐式范围,并Ordering以您喜欢的任何方式实现此方法.这允许您A在实现者A忘记这样做时定义类型对象的排序方式,并在需要非默认排序时重新定义它们的排序方式.