46

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?

4 Answers 4

81

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)

Sign up to request clarification or add additional context in comments.

2 Comments

Sweet! It works like a charm. Thank you very much, @earthw0rmjim!
Here is an even more elegant solution: stackoverflow.com/questions/37259159/…, val sortedList = list.sortedWith(compareByDescending({ it.age }, { it.name }))
11

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

1 Comment

or like this: invoicesList = invoicesList.sortedBy({ it.dt }).reversed()
5
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 }) })

Comments

1

Reversing the comparator also works:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.