使用条件在Kotlin中选择分类属性

我正在使用sortedBy()在对象集合上执行排序。

由于订单可能会根据用户的选择而改变,我已经结束了以下代码

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

然后我对排序的集合执行进一步的操作。 我意识到sortedBy()方法期望一个属性被返回。 我想知道是否有一种方法将排序条件嵌入到一个收集方法链中。

如果你的属性是不同类型的,你将无法根据某些条件选择其中的一个作为sortedBy的结果,因为它们的公共超类型将被推断为Any并且它不是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} 

或者,如果您需要更多的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)} 

你可以做一些事情:

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

您可以将lambda参数传递给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之后继续调用call。