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.