如何将Map [A​​,B]转换为按字符串排序的键值字符串?

时间:2012-06-19 07:46:20

标签: scala

假设我有一张地图:

val m = Map("foo" -> 10, "bar" -> 5)

我想将其转换为以下格式的字符串(键和值用“:”分隔,不同的元素用“,”分隔):

"bar:5,foo:10"

请注意,现在已订购钥匙。

如何编写一个函数来执行此转换?我试过了

def f[A, B](m: Map[A, B]): String = {
  m.toList.sortBy(_._1).map { x => x._1 + ":" + x._2 }.mkString(",")
}

但是这不起作用,因为我需要指定A是可订购的。我不知道该怎么做 - 我尝试在我的函数中添加一个隐式Orderer参数,但它不起作用。

1 个答案:

答案 0 :(得分:8)

使用Ordering类型类:

def f[A: Ordering, B](m: Map[A, B]): String = {
  m.toList.sortBy(_._1).map { x => x._1 + ":" + x._2 }.mkString(",")
}

这会向f添加另一个带有隐式Ordering参数的参数列表。方法签名实际上是在场景后面翻译的:

def f[A, B](m: Map[A, B])(implicit evidence: Ordering[A]): String

然后由evidence选取sortBy参数并用于比较元素。

编辑:

请注意,您不能以与Ordered相同的方式使用OrderingOrdered特征旨在与将要排序的对象类型(如Java中)混合在一起。换句话说,A必须扩展Ordered[A],然后您将其编写为A <: Ordered[A]

但是,使用Ordered的这种继承方法不如使用Ordering的类型类方法强大,因为它不太灵活。如果其他人定义A并且没有决定使其扩展Ordered[A],那么您将无法将其与sortBy一起使用(至少在没有创建包装类的情况下) 。另一方面,您始终可以在范围内声明新的隐式Ordering[A],而无需更改A继承的内容,并以您喜欢的任何方式实现此Ordering。这允许您在A的实现者忘记这样做时定义A类型的对象的排序方式,并在需要非默认排序时重新定义它们的排序方式。 / p>