Kotlin - ArrayList 的自定义排序
Kotlin - custom sorting of ArrayList
我正在构建一个 Android 应用程序,我想在其中实现 User
的自定义排序
让我详细解释一下需求。
假设 ArrayList
类型 User
中存储了 15 个用户,每个用户都有单独的角色映射。用户必须 grouped by roles
顺序相同 as below
。
1.Mechanic
2.Plumber
3.Electrician
此外,在角色组中,它们应该主要根据 unread message count
排序,其次根据 alphabetical order
情况 1:没有未读消息
基于role-based grouping
和alphabetical sorting
(不含未读消息),用户应按以下方式显示。(括号中的'0'表示未读消息数)
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)
情况 2:未读消息计数
当有用户(角色内)有未读聊天记录时,列表应优先考虑他们在列表中的优先顺序,字母顺序应被视为次要。它通常应如下所示。
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)
请帮我完成这个。
下面是我试过的
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
}))
}
这对列表进行排序主要基于未读消息计数,其次基于字母顺序但无法以上述方式完成。
你实际上走对了方向。您只需要另外按角色排序。像这样:
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 }
)
如果你真的需要对项目进行分组而不是仅仅对它们进行排序,那么你需要类似 Map<Role, List<Users>>
的东西,那么:
users.groupByTo(sortedMapOf(compareBy { rolesOrder[it] })) { it.role }
.mapValues { (_, value) ->
value.sortedWith(
compareByDescending<User> { it.unreadMessageCount }
.thenBy { it.firstName }
)
}
如果你有一个有序的角色列表,你需要为它们分配索引,你可以这样做:
val rolesOrder = listOf("Mechanic", "Plumber", "Electrician")
.withIndex()
.associate { it.value to it.index }
请注意,如果 rolesOrder
中缺少角色,用户将被放在开头。如果这是一种可能的情况,并且您想将它们放在末尾,那么可以这样比较角色:
rolesOrder[it.role] ?: Integer.MAX_VALUE
我相信Broot的回答是好的;如果您需要一个“工作示例”,我相信有 smarter/better/more kotlin 方法,但为什么不从简单开始。
5分钟,你就能想出一个例子运行 in the kotlin playground.
本质上:
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)
}
}
输出:
[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)]
我正在构建一个 Android 应用程序,我想在其中实现 User
让我详细解释一下需求。
假设 ArrayList
类型 User
中存储了 15 个用户,每个用户都有单独的角色映射。用户必须 grouped by roles
顺序相同 as below
。
1.Mechanic
2.Plumber
3.Electrician
此外,在角色组中,它们应该主要根据 unread message count
排序,其次根据 alphabetical order
情况 1:没有未读消息
基于role-based grouping
和alphabetical sorting
(不含未读消息),用户应按以下方式显示。(括号中的'0'表示未读消息数)
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)
情况 2:未读消息计数
当有用户(角色内)有未读聊天记录时,列表应优先考虑他们在列表中的优先顺序,字母顺序应被视为次要。它通常应如下所示。
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)
请帮我完成这个。
下面是我试过的
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
}))
}
这对列表进行排序主要基于未读消息计数,其次基于字母顺序但无法以上述方式完成。
你实际上走对了方向。您只需要另外按角色排序。像这样:
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 }
)
如果你真的需要对项目进行分组而不是仅仅对它们进行排序,那么你需要类似 Map<Role, List<Users>>
的东西,那么:
users.groupByTo(sortedMapOf(compareBy { rolesOrder[it] })) { it.role }
.mapValues { (_, value) ->
value.sortedWith(
compareByDescending<User> { it.unreadMessageCount }
.thenBy { it.firstName }
)
}
如果你有一个有序的角色列表,你需要为它们分配索引,你可以这样做:
val rolesOrder = listOf("Mechanic", "Plumber", "Electrician")
.withIndex()
.associate { it.value to it.index }
请注意,如果 rolesOrder
中缺少角色,用户将被放在开头。如果这是一种可能的情况,并且您想将它们放在末尾,那么可以这样比较角色:
rolesOrder[it.role] ?: Integer.MAX_VALUE
我相信Broot的回答是好的;如果您需要一个“工作示例”,我相信有 smarter/better/more kotlin 方法,但为什么不从简单开始。
5分钟,你就能想出一个例子运行 in the kotlin playground.
本质上:
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)
}
}
输出:
[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)]