#android #sorting #kotlin #comparable
#Android #сортировка #kotlin #сопоставимый
Вопрос:
В моем приложении для Android у меня есть список пользовательских объектов, имеющих следующие поля,
var myNotesList: ArrayList<Note>
class Note(
var title: String
var date: String,
var status: String)
Здесь status
может быть любое из следующих трех значений:
Черновик, ожидание, завершено
Теперь я хочу, чтобы мой список был упорядочен таким образом, чтобы сначала были черновики и отсортированы в порядке убывания даты, затем ожидающие сортировки с указанием даты, а затем завершенных элементов статуса.
например,
{someNoteTitle, draft, 07 Jan 2021},
{someNoteTitle, draft, 06 Jan 2021},
{someNoteTitle, draft, 04 Jan 2021},
{someNoteTitle, Pending, 07 Jan 2021},
{someNoteTitle, Pending, 06 Jan 2021},
{someNoteTitle, Completed, 07 Jan 2021},
{someNoteTitle, Completed, 05 Jan 2021},
{someNoteTitle, Completed, 02 Jan 2021}
Я пробовал с sortedWith
помощью and compareBy
, но из-за того, что требование к порядку состояния не является алфавитным, я не могу сделать это с помощью встроенных функций, иначе мне придется делать это грязным способом с помощью циклов.
Ответ №1:
Я не вижу способа без использования некоторых грязных компараторов для сортировки вашего массива, например, для статуса (и для даты это было бы намного грязнее) :
myNotesList.sortedWith(object: Comparator<String> {
override fun compare(a: String, b: String): Int {
return when {
a == "DRAFT" amp;amp; b == "PENDING" -> -1
a == "DRAFT" amp;amp; b == "COMPLETED" -> -1
a == "PENDING" amp;amp; b == "DRAFT" -> 1
a == "PENDING" amp;amp; b == "COMPLETED" -> -1
a == "COMPLETED" amp;amp; b == "PENDING" -> 1
a == "COMPLETED" amp;amp; b == "DRAFT" -> 1
else -> 0
}
}
})
Что я хотел бы сделать, это изменить объект Note, используя типы, которые можно упорядочить так, как я хочу. Если вы не можете изменить объект Note, я бы создал другой объект и создал mapper для сопоставления заметки с новым типом.
Например, сначала я бы создал объект для статуса заметки с перечислением (но вам нужно быть осторожным, так как порядок будет привязан к порядку элементов перечисления, что иногда может вызвать проблемы)
enum class Status {
DRAFT,
PENDING,
COMPLETED
}
Для даты я бы использовал объект Date, LocalDate например. Еще раз, это ваш mapper (если вы не можете изменить объект Note), который позволит вам преобразовать строку date в объект LocalDate .
Итак, ваш конечный объект будет выглядеть так :
class Note(
var title: String,
var date: LocalDate,
var status: Status)
Тогда вы можете просто сделать :
myNotesList.sortedWith(compareBy<Note>({it.status}).thenByDescending({it.date})))
Комментарии:
1. да, я думал об этом подходе к использованию
Enum
, и @IR42 также рекомендовал это в комментарии к моему вопросу. Позвольте мне попробовать с этим, так как мне нужно изменить тип поля даты на String.