Как я могу изменить порядок или отсортировать список на основе двух полей, не имеющих никакого алфавитного или числового порядка в Kotlin?

#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.