mercredi 31 août 2022

How to sort a list based on multiple fields of sublcass dynamically

I am creating a Android Application which show list of Stores. The main Recyclerview shows the list of Store and every store object has SortingData which holds multiple fields like minimumDistance,rating etc.

By user selection i get a list of selected tags which size varies on the base of user selection and want to sort the main list of stores by it.

Every selected tag holds a propery isAscending which shows that it should be sorted in Ascending or Descending order. Lets say Rating with be Descending and Minimum Distance will be ascending and so on.

I have written a custom comparator to do so, to avoid multiple if conditions inside a loop but this comparator has issues. Like, its sorting the intergers based on first digit only doubles are also not sorted well.

Below is my code

data class Store(
    val name: String,
    val sortingData: SortingData,
    val status: String
) {
}
data class SortingData(
    val averageProductPrice: Int,
    val bestMatch: Double,
    val deliveryCosts: Int,
    val distance: Int,
    val minCost: Int,
    val newest: Double,
    val popularity: Double,
    val ratingAverage: Float
)

data class SortTag(var text: String, var key:String,var isSelected: Boolean,var isAscending:Boolean) {
}

Function

fun sortListByAdditionalTags(
    list: MutableList<Store>>,    selectedTags: List<SortTag>
): MutableList<Store> {
    /*
 Best Match -> Descending highest value on top
 Newest -> Descending highest value on top
 Rating Average -> Descending highest value on top
 Distance -> Ascending lowest value on top
 Popularity -> Descending highest value on top
 Average Product Price ->  Ascending lowest value on top
 Delivery cost ->  Ascending lowest value on top
 Min cost->  Ascending lowest value on top
 */
    var sorted = list
    selectedTags.forEach {
        sorted = list.sortedWith(
            comparator = AdditionalSortComparator(
                it.key,
                it.isAscending
            )
        ) as MutableList< Store 
>

    }
    return sorted

}

Custom Sort Comparator

class AdditionalSortComparator(
    private val sortProperty: String? = null,
    private val isAscending: Boolean
) : Comparator<Store> {
    override fun compare(o1: Store?, o2: Store?): Int {
        val sortingData =
            Store::class.declaredMemberProperties.firstOrNull { it.name == "sortingData" }

        val s1: sortingData = o1?.let { sortingData?.get(it) } as sortingData
        val s2: sortingData = o2?.let { sortingData?.get(it) } as sortingData

        val calledVariable = SortingData::class.declaredMemberProperties.firstOrNull { it.name == sortProperty }
        return if (calledVariable != null) {
            if (calledVariable.get(s1) is Int) {
                val valueFirst = calledVariable.get(s1) as Int
                val valueSecond = calledVariable.get(s2) as Int
                if (isAscending) valueFirst - valueSecond else valueSecond - valueFirst
            } else if (calledVariable.get(s1) is Float) {
                val valueFirst = calledVariable.get(s1) as Float
                val valueSecond = calledVariable.get(s2) as Float
                if (isAscending) valueFirst - valueSecond else valueSecond - valueFirst
            } else if (calledVariable.get(s1) is Double) {
                val valueFirst = calledVariable.get(s1) as Double
                val valueSecond = calledVariable.get(s2) as Double
                if (isAscending) abs(valueFirst-valueSecond) else abs(valueSecond-valueFirst)
            }

            if (isAscending) calledVariable.get(s1).toString()
                .compareTo(calledVariable.get(s2).toString())
            else calledVariable.get(s2).toString()
                .compareTo(calledVariable.get(s1).toString())
        } else {
            val idProperty = Store::name
            val valueFirst = idProperty.get(o1)
            val valueSecond = idProperty.get(o2)
            if (isAscending) valueFirst.compareTo(valueSecond) else valueSecond.compareTo(valueFirst)
        }
    }
}

The dependency i used for Kotlin Reflection is

implementation("org.jetbrains.kotlin:kotlin-reflect:1.7.10")

Can somebody please help me out with this, how i can achieve this functionality in an efficient and correct manner?





Aucun commentaire:

Enregistrer un commentaire