How to sort in descending order using multiple com

2020-04-01 22:01发布

问题:

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?

回答1:

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)



回答2:

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()



回答3:

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 }) })


回答4:

Reversing the comparator also works:

originalItems.sortedWith(compareBy<Item>({ it.localHits }, { it.title }).reversed())


标签: kotlin