Использование условия для выбора свойства сортировки в Котлине

Я использую sortedBy() для выполнения сортировки по коллекции объектов.

Поскольку заказ может меняться в зависимости от выбора пользователя, я получил следующий код

 val sortedList = if (sortingOrder == WordSortingOrder.BY_ALPHA) { list.sortedBy { it.word.value } } else { list.sortedBy { it.createdAt } } 

Затем я выполняю дальнейшие действия по сортировке коллекции. Я понимаю, что sortedBy() ожидает возврата свойства. Интересно, есть ли способ встроить условие сортировки в одну цепочку методов сбора.

Если ваши свойства имеют разные типы, вы не сможете выбрать один из них на основе некоторого условия в качестве результата для sortedBy , так как их общий супертип будет выведен как Any и это не подтип sortedBy Comparable<R> как sortedBy надеется.

Вместо этого вы можете использовать метод sortedWith , который принимает Comparator , и предоставляет компаратор в зависимости от условия:

 list.sortedWith( if (sortingOrder == WordSortingOrder.BY_ALPHA) compareBy { it.word.value } else compareBy { it.createdAt } ) 

Здесь создаются компараторы для разных свойств с функцией kotlin.comparisons.compareBy .

Затем вы можете извлечь логику, которая выбирает компаратор на основе порядка сортировки для функции:

 list.sortedWith(comparatorFor(sortingOrder)) fun comparatorFor(sortingOrder: WordSortingOrder): Comparator<MyType> = ... 

sortedBy ожидает в качестве параметра любой функции типа (T) -> R Свойство является краеугольным камнем этого.

Это означает, что вы можете это сделать:

 val sortedList = list .sortedBy { if (sortingOrder == WordSortingOrder.BY_ALPHA) it.word.value else it.createdAt} 

Или, если вам нужно что-то большее ООП-иш:

 enum class WordSortingOrder(val transform: (MyObject) -> Int) { BY_ALPHA({it.word.value}), BY_ALPHA_REVERSED({-1 * it.word.value}), DEFAULT({it.createdAt}) } val sortedList = list.sortedBy { sortingOrder.transform(it)} 

Вы можете сделать что-то вроде:

 list.sortedBy { item -> when(sortingOrder) { WordSortingOrder.BY_ALPHA -> item.word.value else -> item.createdAt } } 

Вы можете sortedBy аргумент лямбда в sortedBy условно:

 list.sortedBy(if (sortingOrder == WordSortingOrder.BY_ALPHA) { { it: MyType -> it.word.value } } else { { it: MyType -> it.createdAt } }) 

Вы можете использовать, when вместо этого читаете в этом сценарии:

 list.sortedBy(when (sortingOrder) { WordSortingOrder.BY_ALPHA -> { it: MyType -> it.word.value } else -> { it: MyType -> it.createdAt } }) 

Если у ваших селекторов есть разные типы возвращаемых данных, вы можете просто обернуть свой существующий код в list.let { list -> ... } или использовать run :

 list.run { if (sortingOrder == WordSortingOrder.BY_ALPHA) { sortedBy { it.word.value } } else { sortedBy { it.createdAt } } } 

Затем вы можете продолжить вызов вызовов после let / run .

Intereting Posts
пустой конструктор классов данных для Firebase Не удалось установить ViewModel на Kotlin Kotlin: видимый делегат свойства nullable Ошибка: конфликт с зависимостью «com.google.code.findbugs: jsr305» Kotlin 'небезопасный вызов ошибки компиляции с помощью NULL-приемника после нулевой проверки Почему прокрутка ViewPager перед тем, как изменить его заполнение и pagemargin, полностью подвела его? Метод вызова из класса Kotlin Класс Android не найден Intermitten и распространяется через код Как работает синтаксис доступа к свойствам Kotlin для классов Java (например, EditText setText)? Можно ли использовать javascript из источников Kotlin в JVM? Как использовать метод Realm в методе с Kotlin Почему я не могу добавить два номера в Котлин, используя этот исходный код? AsyncTask без утечек Связывание с JMM классами, определенными asm из Kotlin с использованием Gradle Kotlin: Модифицировать (неизменный) Список через бросок, это законно?