Echo
Echo

Reputation: 3029

Sort map by value

I have List[(String,String)] and I need to sort them by the 2nd value and return a map

I have done the following:

val newMap = list.sortBy(_._2).foldLeft(Map.empty[String, String]) {
      (map, key) ⇒ map + (key._1 → key._2)
    }

list is a List[(String,String)]

However the returnning map isn't sorted!!

Upvotes: 5

Views: 5686

Answers (3)

Julian Dehne
Julian Dehne

Reputation: 83

This should be as simple as:

val input = List((1,1), (3,4), (20,19), (2,2))
val output = input.sortBy(_._2).toMap

output is:

Map(1->1, 2->2, 3->4, 20->19)

Upvotes: 1

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340693

Default Map implementations are hash-based and they do not preserve order. Instead use scala.collection.mutable.LinkedHashMap:

val newMap = list.sortBy(_._2).foldLeft(new LinkedHashMap[String, String]) {
    (map, key) => map += (key._1 -> key._2)
    map
}

As suggested by @Rex Kerr, scala.collection.immutable.ListMap might be a better choice for target type:

val newMap = list.sortBy(_._2).foldLeft(new ListMap[String, String]) {
    (map, key) => map + (key._1 -> key._2)
}

Or (once again full credits should go to @Rex Kerr):

val newMap = new ListMap() ++ list.sortBy(_._2)

However what do you really want to achieve? Looks like you might be choosing wrong data structure...

Upvotes: 9

oxbow_lakes
oxbow_lakes

Reputation: 134270

My assumption from your question (which is not 100% clear): you wish to have a Map[A, B] which is sorted according to B

This is not possible; the scala sorted map is SortedMap[A, B] and this has to be sorted according to some ordering on the type A.

If all you want is a traversable sequence of pairs (A, B) according to B, then you have no need for a Map and the solution:

list sortBy (_._2)

...will suffice. If you wish to have a Map, then Tomasz's answer looks enticing - but it is misleading. The map is not sorted; it is traversable in a known order (the order of insertion). This is not the same thing - subsequent additions to the Map will appear at the end (from a traversal perspective) regardless of what the value is. So I think you need to ask yourself a question: what am I trying to do?

If you care about traversing a sequence of pairs according to the second elements, you don't need a Map at all.

Upvotes: 2

Related Questions