Home > Net >  Kotlin sortedMap compared by the Pair value not the key
Kotlin sortedMap compared by the Pair value not the key

Time:08-05

I found this statement

sortedMapOf(compareBy<String> { it.length }, Pair("abc", 1), Pair("c", 3), Pair("bd", 4), Pair("bc", 2))

So it sorts first by the length of the key. However what I need is a sort by the value of the map's pairs.

Therefore I tried this:

mapOf("eat" to 11.0, "sleep" to 50.0).toSortedMap(Comparator<Pair<String, Double>> { o1, o2 -> o1.second.compareTo(o2.second) })

For some reason the part Comparator<Pair<String, Double>> { o1, o2 -> o1.second.compareTo(o2.second) } gives me an error.

My IDE (IntelliJ) tells me this:

Type mismatch.
Required: Pair<String, Double>
Found: String

I don't get it where am I passing a String. All I can see is me using the Pair.

CodePudding user response:

Key in mapOf("eat" to 11.0, "sleep" to 50.0) is of type String, hence toSortedMap is expecting you to provide a comparator that takes string as argument.

To make the code runnable, you'll have to make a new map where the key is of type Pair<String, Double>.

mapOf("eat" to 11.0, "sleep" to 50.0)
    .map { Pair(it.key, it.value) to it.value }
    .toMap()
    .toSortedMap { o1, o2 -> o1.second.compareTo(o2.second) }

This is of course strange code, but it should answer the question.

CodePudding user response:

SortedMaps are sorted on their keys - you can't sort them on their values. And here's the signature of sortedMapOf():

fun <K, V> sortedMapOf(
    comparator: Comparator<in K>,
    vararg pairs: Pair<K, V>
): SortedMap<K, V>

The comparator you're passing in explicitly takes the key's type, i.e. the first value of each Pair is getting passed to the comparator, not the whole Pair.

That's why you're getting the error about Strings and Pairs - you told the Comparator that it's getting keys that are Pair<String, Double>s, but the Map you're passing in has String keys and Double values (since a Pair is treated as a key/value item).

You can't do what you're trying to do, basically! Is there another way to achieve whatever you're doing? A typical approach would be to just use a normal map, and make a sorted list when you need the output:

val myMap = mapOf("eat" to 11.0, "sleep" to 50.0)
val sorted = myMap.entries.sortedBy {it.value}
  • Related