#android #sorting #kotlin #arraylist
Вопрос:
Я создаю приложение для Android, в котором я хотел бы реализовать пользовательскую сортировку User
Позвольте мне подробно объяснить это требование.
Предположим, что в типе of хранится 15 пользователей ArrayList
User
, и у каждого пользователя будет отдельное сопоставление ролей. Пользователи должны находиться 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
}))
}
Это сортирует список в первую очередь на основе количества непрочитанных сообщений и во вторую очередь на основе алфавитного порядка, но не может выполнить вышеупомянутым способом.
Комментарии:
1. Вероятно, вам сначала придется использовать groupBy , чтобы сгруппировать их.
2. @MartinMarconcini Как этого добиться? Пожалуйста, помогите мне. сначала на нем должны отображаться, если таковые имеются, механики, затем электрики, а затем сантехники.
Ответ №1:
Вы действительно пошли в правильном направлении. Вам просто нужно дополнительно отсортировать по роли. Что-то вроде этого:
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
Комментарии:
1. Спасибо. И, конечно, позвольте мне попробовать это и вернуться как можно скорее.
2. Я пытался. Сортировка по алфавиту и количеству чатов работает нормально, но группировка не происходит 🙁 Пожалуйста, помогите мне.
3. Что вы имеете в виду, говоря, что группировки не происходит? Роли игнорируются при сортировке, поэтому они перепутаны в списке результатов?
4. ДА. Я только что попробовал это.val rolesOrder = mapOf(«Механик» до 1, «Сантехник» до 2, «Электрик» до 3) пользователи.Сортируются с( по сравнению с<Пользователем> { rolesOrder[it.роль] } .Затем опускается { it.unreadMessageCount } .Затем { it.Имя } )
5. Извините, я не понимаю вашего вопроса. Вы просто скопировали и вставили мой код в комментарий. Я точно знаю, что оба примера сортировки и группировки работают правильно, потому что я проверил их перед публикацией. Если это не работает для вас, то вам, вероятно, придется добавить больше информации в вопрос: каков точный код, который вы использовали, каков результат и почему он отличается от ожидаемого.
Ответ №2:
Я считаю, что ответ Брута хорош; если вам нужен «рабочий пример», я уверен, что есть более разумные/лучшие/более эффективные способы котлина, но почему бы не начать с простого.
За 5 минут вы можете придумать пример, запущенный на игровой площадке kotlin.
По существу:
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)]