Usar condición para seleccionar la propiedad de sorting en Kotlin

Estoy utilizando sortedBy() para realizar la sorting en la colección de objects.

Como la order puede cambiar dependiendo de la elección del usuario, he terminado con el siguiente código

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

Luego realizo más acciones en la colección orderada. Me doy count de que el método sortedBy() espera que se devuelva una propiedad. Me pregunto si hay una manera de integrar la condición de sorting en una cadena de methods de recolección.

Si sus properties son de types diferentes, no podrá seleccionar una de ellas en function de alguna condición como resultado de sortedBy , ya que su sortedBy común se inferiría como Any y no es un subtipo de Comparable<R> como sortedBy espera

En su lugar, puede utilizar sortedWith método, que toma un Comparator , y proporcionar un comparador en function de la condición:

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

Aquí se crean comparadores para diferentes properties con la function kotlin.comparisons.compareBy .

A continuación, puede extraer la lógica que selecciona el comparador según el order de sorting de una function:

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

The sortedBy espera que cualquier function de tipo (T) -> R sea ​​su parámetro. Una propiedad es un caso de esquina de eso.

Lo que significa que puedes hacer esto:

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

O, si necesita algo más OOP-ish:

 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)} 

Puedes hacer algo como:

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

Puede hacer que el argumento lambda pase a sortedBy condicional:

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

Puede encontrar el uso de when lugar de if más legible en este escenario:

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

Si sus selectores tienen diferentes types de devolución, puede simplemente ajustar su código existente dentro de list.let { list -> ... } o usar run :

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

A continuación, puede seguir chainging llamadas después de la let / run .

  • Getters y Setters en Kotlin
  • Verificando si la cadena está vacía en Kotlin
  • Kotlin: ambigüedad de resolución de sobrecarga en Eclipse, pero no en IntelliJ
  • ¿Cómo uso el object Kotlin por reflexión?
  • Compruebe si EditText está vacío mientras calcula los numbers
  • Nueva architecture con Dagger y Kotlin
  • Analizando json en Java Pojos con Gson de Kotlin falta información genérica
  • Objetos Kotlin vs compañero-object vs methods con ámbito de package
  • Smart Cast no funciona como se esperaba
  • Se llama a Android RxJava onNext incluso cuando se anula la suscripción del observador
  • Evite el conflicto de time de ejecución / stdlib de Kotlin con otros complementos