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.
CodePudding user response:
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
CodePudding user response:
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)]