使用条件在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。