Scala map sorting

2020-05-15 15:17发布

问题:

How do I sort a map of this kind:

"01" -> List(34,12,14,23), "11" -> List(22,11,34)

by the beginning values?

回答1:

One way is to use scala.collection.immutable.TreeMap, which is always sorted by keys:

val t = TreeMap("01" -> List(34,12,14,23), "11" -> List(22,11,34))

//If  you have already a map...
val m = Map("01" -> List(34,12,14,23), "11" -> List(22,11,34))
//... use this
val t = TreeMap(m.toSeq:_*)

You can convert it to a Seq or List and sort it, too:

//by specifying an element for sorting
m.toSeq.sortBy(_._1) //sort by comparing keys
m.toSeq.sortBy(_._2) //sort by comparing values

//by providing a sort function
m.toSeq.sortWith(_._1 < _._1) //sort by comparing keys

There are plenty of possibilities, each more or less convenient in a certain context.



回答2:

As stated, the default Map type is unsorted, but there's always SortedMap

import collection.immutable.SortedMap
SortedMap("01" -> List(34,12,14,23), "11" -> List(22,11,34))

Although I'm guessing you can't use that, because I recognise this homework and suspect that YOUR map is the result of a groupBy operation. So you have to create an empty SortedMap and add the values:

val unsorted = Map("01" -> List(34,12,14,23), "11" -> List(22,11,34))
val sorted = SortedMap.empty[String, List[Int]] ++ unsorted
//or
val sorted = SortedMap(unsorted.toSeq:_*)

Or if you're not wedded to the Map interface, you can just convert it to a sequence of tuples. Note that this approach will only work if both the keys and values have a defined ordering. Lists don't have a default ordering defined, so this won't work with your example code - I therefore made up some other numbers instead.

val unsorted = Map("01" -> 56, "11" -> 34)
val sorted = unsorted.toSeq.sorted

This might be useful if you can first convert your lists to some other type (such as a String), which is best done using mapValues

update: See Landei's answer, which shows how you can provide a custom sort function that'll make this approach work.