如何在Scala中对Map内的Map进行排序

时间:2012-10-23 09:09:03

标签: scala

我已经定义了Map[Int, Map[String, Int]]

我知道如何使用ListMap对外部Map进行排序。例如:

实际上所有地图都是可变的。

var myMap: Map[ Int, scala.collection.mutable.Map[String, Int] ] = Map()
....
// add some items to myMap
....
var sortedMap = scala.collection.immutable.ListMap( myMap.toList.sortBy{_._1}:_* )

但是如何根据String对内部Map进行排序?

以下似乎是错误的:

myMap foreach {
    case ( num, map ) ⇒ 
        map = scala.collection.immutable.ListMap( map.toList.sortBy{_._1}:_* ) 
}

编译器说map: reassignment to val,但我已将内部地图定义为mutable.Map。我该怎么办?

3 个答案:

答案 0 :(得分:0)

您可以使用mapValues将函数应用于每个值,然后将相同的排序函数应用于第二个映射。

import scala.collection.immutable.ListMap

val myMap = Map[ Int, scala.collection.mutable.Map[String, Int] ] = Map()
....
// add some items to myMap
....
val outerSortedMap = ListMap(myMap.toList.sortBy{_._1}:_* )
val innerSortedMap = myMap.mapValues(innerMap => 
  ListMap(innerMap.toList.sortBy{_._1}:_* )
)

对内部和外部地图​​进行排序

为此,您只需先对外部地图进行排序(以便按上述说明获得outerSortedMap),然后对outerSortedMap的内部地图进行排序。

val innerOuterSortedMap = outerSortedMap.mapValues(innerMap =>
  ListMap(innerMap.toList.sortBy{_._1}:_*)
)

关于您的尝试

foreach方法具有以下签名:foreach[U](f: ((A, B)) ⇒ U): Unit,因此它是一种副作用方法。你想要的是将函数应用于map的所有值,然后用函数的结果替换值。这基本上是一个map函数(是map代表两个完全不同的东西),并且当你想要映射值时,函数mapValues就存在了!

答案 1 :(得分:0)

您还可以考虑使用TreeMap。这样您以后就不需要对地图进行排序了。

请注意,没有可变的TreeMap,但这不是一个大问题(也许它甚至是故意的)。具有可变TreeMap并没有带来相当大的好处,因为向平衡树添加元素需要 O(log n),无论我们是否认为结构是可变的或不可变的。 / p>

这也意味着使用TreeMap具有与稍后进行其他类型的收集和排序相同的渐近复杂性。将 n 元素添加到TreeMap将采用 n O(log n)= O(n log n),这与排序列表相同 n 元素。

另请注意,TreeMap的构造函数具有隐式参数ordering: Ordering[A]。通过在创建地图时明确设置它,如果要使用与默认值不同的标准进行排序,则可以插入自己的排序功能。

答案 2 :(得分:0)

如果你为自己定义一个sortMap辅助函数,那就很干净了:

def sortMap[K: Ordering, V](m: scala.collection.Map[K, V]) = 
  ListMap(m.toList.sortBy { _._1 }: _*)

val doubleSortedMap = sortMap(myMap.mapValues(sortMap(_)))