Chris Legge
Chris Legge

Reputation: 789

kotlin datatable structure to hold and sort data

So i have this strucuture that i use to hold data in that will feed a kotlin/js table

data class TableData<T : Any>(
    var items: List<T>,
    var fieldList: MutableList<KProperty1<T, Comparable<*>>> = mutableListOf(),
) : Iterable<T> {
    override fun iterator() = items.iterator()

    fun handleSortRequest(incoming: KProperty1<T, Comparable<*>>) {
        fieldList.add(incoming)
        fieldList.reverse()
        items = items.sortedWith(compareBy(*fieldList.toTypedArray()))
    }
}

and it works great, i am able to sort each column via something like

 sort(Meal::calories)

I would like to expand upon it by adding arrows to the columns for ascending and descending like many of the popular data tables, is this possible? How would i do it.

my test class is

data class Meal(
    val calories: Int,
    val salad: String,
    val mainCourse: String,
    val desert: String,
)

and i feed the table with this list of meals.

val mealList = listOf(
    Meal(calories = 90, salad = "Fruit Salad", mainCourse = "Pork", desert = "cookies"),
    Meal(calories = 10, salad = "Shrimp Salad", mainCourse = "Burgers", desert = "cookies"),
    Meal(calories = 30, salad = "Tuna Salad", mainCourse = "Chicken", desert = "pie"),
    Meal(calories = 40, salad = "Cobb Salad", mainCourse = "Steak", desert = "jello"),
    Meal(calories = 40, salad = "Caesar Salad", mainCourse = "Salmon", desert = "pudding"),
    Meal(calories = 40, salad = "Potato Salad", mainCourse = "Hot Dogs", desert = "cake"),
    Meal(calories = 20, salad = "Garden Salad", mainCourse = "Eggs", desert = "ice cream"),
)

Upvotes: 0

Views: 1167

Answers (1)

Obviously, you need to pass another parameter to your handleSortRequest method, specifying the sort direction. Also, you need to change the type of items stored in fieldList to store selectors alongside with sort direction.

Now, a comparator could be built from this data:

data class TableData<T : Any>(
    var items: List<T>,
    var fieldList: MutableList<Pair<KProperty1<T, Comparable<*>>, Boolean>> = mutableListOf(),
) : Iterable<T> {
    override fun iterator() = items.iterator()

    fun handleSortRequest(incoming: KProperty1<T, Comparable<*>>, isAscending: Boolean = true) {
        fieldList.add(incoming to isAscending)
        fieldList.reverse()
        
        val comparator = fieldList
            .map { (selector, isAsc) -> if (isAsc) compareBy(selector) else compareByDescending(selector) }
            .reduce { acc, x -> acc.thenComparing(x) }

        items = items.sortedWith(comparator)
    }
}

Upvotes: 1

Related Questions