0

I am building an Android application in which I would like to implement the custom sorting of User

Let me explain the requirement in detail.

Let's assume that there are 15 users stored in the ArrayList of type User and each users will have separate role mapping. The users must be grouped by roles in the same order as below.

 1.Mechanic 
 2.Plumber 
 3.Electrician

Also, within the role groups they should be sorted primarily based on unread message count and secondarily based on alphabetical order

Case 1: Without Unread messages

Based on role-based grouping and alphabetical sorting(without unread messages), the users should be displayed in the following way.(The '0' in the bracket indicates the unread messages count)

Aarav,Mechanic(0)
Dhruv,Mechanic(0)
Jason,Mechanic(0)
Pranav,Mechanic(0)
Zeplin,Mechanic(0)

Amit,Plumber(0)
Baskaran,Plumber(0)
Garry,Plumber(0)
Rakesh,Plumber(0)
Shekar,Plumber(0)

Balu,Electrician(0)
Ragunathan,Electrician(0)
Prem kumar,Electrician(0)
Saravanan,Electrician(0)
Thanigaivel,Electrician(0)

Case 2: With unread messages count

When there are users(within role) with unread chat counts, the list should prioritize them primarily in the list and the alphabetical order should be considered as secondary. It should typically look like below.

Zeplin,Mechanic(20)
Pranav,Mechanic(10)
Aarav,Mechanic(0)
Dhruv,Mechanic(0)
Jason,Mechanic(0)

Garry,Plumber(5)
Rakesh,Plumber(5)
Amit,Plumber(0)
Baskaran,Plumber(0)
Shekar,Plumber(0)

Prem kumar,Electrician(10)
Balu,Electrician(0)
Ragunathan,Electrician(0)
Saravanan,Electrician(0)
Thanigaivel,Electrician(0)

Please help me to accomplish this.

Below is what I have tried

 fun getListWithGroupingAndSorting(){
      val users = ArrayList<User>
     // Writing logic to pull list of users from server and assigning to `users`
        return ArrayList(users.sortedWith(compareByDescending<User> {
            it.unreadMessageCount
        }.thenBy {
            it.firstName
        }))
    
    }

This sorts the list primarily based on unread message count and secondarily based on alphabetical order but unable to accomplish in the above mentioned way.

2
  • You're probably going to have to use groupBy first, to group them. Commented Oct 18, 2021 at 10:11
  • @MartinMarconcini How to accomplish? Please help me out. first it should display if any mechanics and then Electricians and then plumbers. Commented Oct 18, 2021 at 10:15

2 Answers 2

3

You actually went into right direction. You just need to additionally sort by the role. Something like this:

val rolesOrder = mapOf("Mechanic" to 1, "Plumber" to 2, "Electrician" to 3)

users.sortedWith(
    compareBy<User> { rolesOrder[it.role] }
        .thenByDescending { it.unreadMessageCount }
        .thenBy { it.firstName }
)

If you really need to group items instead of just sorting them, so you need something like Map<Role, List<Users>>, then:

users.groupByTo(sortedMapOf(compareBy { rolesOrder[it] })) { it.role }
    .mapValues { (_, value) ->
        value.sortedWith(
            compareByDescending<User> { it.unreadMessageCount }
                .thenBy { it.firstName }
        )
    }

If you have an ordered list of roles and you need to assign indexes to them, you can do it like this:

val rolesOrder = listOf("Mechanic", "Plumber", "Electrician")
    .withIndex()
    .associate { it.value to it.index }

Note that if the role is missing in the rolesOrder, the user will be put at the beginning. If this is a possible case and you would like to put them at the end, then compare roles like this:

rolesOrder[it.role] ?: Integer.MAX_VALUE
Sign up to request clarification or add additional context in comments.

8 Comments

Thank you. And, Sure, let me try this out and get back ASAP.
I have tried. The sorting based on alphabetical order and chat count work fine but the grouping does not happen :-( Please help me out.
What do you mean that grouping does not happen? Roles are ignored while sorting, so they're mixed up in the result list?
Yes. I have just tried this.val rolesOrder = mapOf("Mechanic" to 1, "Plumber" to 2, "Electrician" to 3) users.sortedWith( compareBy<User> { rolesOrder[it.role] } .thenByDescending { it.unreadMessageCount } .thenBy { it.firstName } )
Sorry, I don't understand your question. You just copy&pasted my code into the comment. I know for sure that both examples for sorting and grouping work properly, because I tested them before posting. If it doesn't work for you then you probably have to add more information into the question: what is the exact code that you used, what is the result and why it is different than expected.
|
1

I believe Broot's answer is fine; if you need a "working example", I'm sure there are smarter/better/more kotlin ways, but why not start simple.

In 5 minutes, you can come up with an example running in the kotlin playground.

Essentially:

data class User(val role: String, val unread: Int = 0)

fun main() {
    val unsorted = listOf(User("Mechanic", 5), 
                          User("Plumber", 3),
                          User("Electrician", 2),
                          User("Mechanic", 9),
                          User("Mechanic", 1),
                          User("Electrician", 8),
                          User("Mechanic", 4),
                          User("Plumber", 0))
    
    // Group them
    val sortedByRole = unsorted
        .groupBy { it.role }
        .forEach { k, group ->  
           val sortedGroup = group.sortedByDescending { user -> user.unread }
           println(sortedGroup)
        } 
}

Output:

[User(role=Mechanic, unread=9), User(role=Mechanic, unread=5), User(role=Mechanic, unread=4), User(role=Mechanic, unread=1)]
[User(role=Plumber, unread=3), User(role=Plumber, unread=0)]
[User(role=Electrician, unread=8), User(role=Electrician, unread=2)]

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.