1

I have a problem that I really cannot solve.. Maybe You may help me. I need to sort an object list from API return that contains filters. The problem is those filters are dynamic, The object Order (the problematic filter) :

class Order(val field : String, val direction: String)

The field is an object attribute (column), the direction can be ASC or DESC. The JSON can return more than one filter, so this can be :

order : {
    field : "id",
    direction : "ASC"
        },
        {
    field : "creationDate"
    direction : "DESC"
        }

The problem is, I don't know how to create a dynamic function that can create a perfect sort in my list. I know I've got to do this :

return list.sortedWith(compareBy(List::id).thenByDescending(List::creationDate))

But Dynamically.. wow

KT

2 Answers 2

2

You can create a map from a property name to the comparator that compares orders by that property:

    val comparators = mapOf<String, Comparator<Order>>(
            "field" to compareBy { it.field },
            "direction" to compareBy { it.direction }
    )

Then you can pick comparators from that map by the given property names, change their sorting order with Comparator.reversed() extension function, and finally combine all these comparators into the single resulting comparator with Comparator.then(Comparator) function:

    val givenOrder = listOf("field" to "ASC", "direction" to "DESC")

    val resultingOrder = givenOrder
        .map { (fieldName, direction) -> 
            comparators[fieldName]!!.let { if (direction == "DESC") it.reversed() else it }
        }
        .reduce { order, nextComparator -> order.then(nextComparator) } 

    val sortedList = list.sortedWith(resultingOrder)
Sign up to request clarification or add additional context in comments.

Comments

1

I am guessing that the second ordering oly applies to those where the first is the same value sortedWith + compareBy

compareBy takes a vararg of selectors which is just a array, so it can be constructed

val selectors: Array<(T) -> Comparable<*>?> = orders.map { TODO() }.toArray()
list.sortedWith(compareBy(*selectors))

i am thinking some extra function go go though all possible fields you could sort and uses either it.field or -(it.field) to create the selectors

also see this answer: Sort collection by multiple fields in Kotlin

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.