Home > other >  Sort a map of objects indescending order
Sort a map of objects indescending order

Time:12-02

In Kotlin, I have a map of objects. The key is a string and the object stored with the key is an object. I want to sort the map in descending order by a property in the object. In this example, I want to sort by timestamp:

data class Image(val timestamp: Long)

val map = mutableMapOf<String, Image>()
map.put("a") = 999
map.put("b") = 555
map.put("c") = 333
map.toSortedMap.... Not sure of the rest

When sorted, the items should be arranged as: c, b, a

Not sure how to implement the sorting.

CodePudding user response:

First, the syntax for creating the map is:

val map = mutableMapOf<String, Image>()
map["a"] = Image(999)
map["b"] = Image(555)
map["c"] = Image(333)

Secondly, you can't sort a map by its values. This is the basic definition of a map. The sort key must be at least part of the map key, which is a string. Perhaps you might be able to use a List<Pair<String, Image>> instead; then you can sort by image just by supplying the appropriate Comparator.

CodePudding user response:

There no direct method to sort Map by value but can transform it to a List and sort the List then transform it back to Map.

I create these twi extension functions that is going to do that for us:

Normal sort:

inline fun <T, R, V: Comparable<V>> MutableMap<T, R>.sortBy(
    crossinline selector: (R) -> V?
) {
    val sortedMap = this.toList().sortedBy { (_, value) -> selector(value) }.toMap()
    this.clear() // delete all the elements from the map
    this.putAll(sortedMap) // add the sorted elements by order
}

Sort by descending:

inline fun <T, R, V: Comparable<V>> MutableMap<T, R>.sortByDescending(
    crossinline selector: (R) -> V?
) {
    val sortedMap = this.toList().sortedByDescending { (_, value) -> selector(value) }.toMap()
    this.clear() // delete all the elements from the map
    this.putAll(sortedMap) // add the sorted elements by order
}

And then you can simple use them like that:

fun main() {
    val map = mutableMapOf<String, Image>()
    map["a"] = Image(333)
    map["b"] = Image(555)
    map["c"] = Image(999)

    println(map) // before: {a=Image(timestamp=333), b=Image(timestamp=555), c=Image(timestamp=999)}
    map.sortByDescending { it.timestamp }
    println(map) // after: {c=Image(timestamp=999), b=Image(timestamp=555), a=Image(timestamp=333)}
}

Note: I don't think that sorting Map by value is a good practice, you can think of working with List instead, but that's how you can sort Map by its value.

  • Related