Kotlin allows me to sort ASC and array using multiple comparison fields.
For example:
return ArrayList(originalItems)
.sortedWith(compareBy({ it.localHits }, { it.title }))
But when I try sort DESC (compareByDescending()
), it does not allow me to use multiple comparison fields.
Is there any way I can do it?
You could use the thenByDescending()
(or thenBy()
for ascending order) extension function to define a secondary Comparator
.
Assuming originalItems
are of SomeCustomObject
, something like this should work:
return ArrayList(originalItems)
.sortedWith(compareByDescending<SomeCustomObject> { it.localHits }
.thenByDescending { it.title })
(of course you have to replace SomeCustomObject
with your own type for the generic)
You can also just use sort ASC and then reverse it:
return ArrayList(originalItems).sortedWith(compareBy({ it.localHits }, { it.title })).asReversed()
The implementation of the asReversed()
is a view of the sorted list with reversed index and has better performance than using reverse()
ArrayList(originalItems)
.sortedWith(compareByDescending({ it.localHits }, { it.title }))
You only need to define this function:
fun <T> compareByDescending(vararg selectors: (T) -> Comparable<*>?): Comparator<T> {
return Comparator { b, a -> compareValuesBy(a, b, *selectors) }
}
Or you may use the Comparator
directly:
ArrayList(originalItems)
.sortedWith(Comparator { b, a -> compareValuesBy(a, b, { it.localHits }, { it.title }) })
Reversing the comparator also works:
originalItems.sortedWith(compareBy<Item>({ it.localHits }, { it.title }).reversed())