Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用条件选择Kotlin中的排序属性_Kotlin - Fatal编程技术网

使用条件选择Kotlin中的排序属性

使用条件选择Kotlin中的排序属性,kotlin,Kotlin,我正在使用sortedBy()对对象集合执行排序 由于顺序可能会根据用户的选择而改变,因此我最终得到了以下代码 val sortedList = if (sortingOrder == WordSortingOrder.BY_ALPHA) { list.sortedBy { it.word.value } } else { list.sortedBy { it.createdAt }

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

由于顺序可能会根据用户的选择而改变,因此我最终得到了以下代码

val sortedList = if (sortingOrder == WordSortingOrder.BY_ALPHA) {
                    list.sortedBy { it.word.value }
                } else {
                    list.sortedBy { it.createdAt }
                }
然后对已排序的集合执行进一步的操作。 我意识到
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
    }
}

您可以通过
将lambda参数设置为有条件的:

list.sortedBy(if (sortingOrder == WordSortingOrder.BY_ALPHA) {
    { it: MyType -> it.word.value }
} else {
    { it: MyType -> it.createdAt }
})
在这种情况下,您可能会发现使用
when
而不是
if
更具可读性:

list.sortedBy(when (sortingOrder) {
    WordSortingOrder.BY_ALPHA -> { it: MyType -> it.word.value }
    else -> { it: MyType -> it.createdAt }
})
如果您的选择器具有不同的返回类型,则您可以简单地将现有代码包装在
列表中。让{list->…}
或使用
运行

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

然后,您可以在运行
后继续链接调用
/
如果您的属性属于不同的类型,您将无法根据某些条件为
排序后的
选择其中一个,因为它们的常见超类型将被推断为
Any
,并且它不是
可比的
的子类型,正如
所分类的那样

相反,您可以使用
sortedWith
方法,该方法采用
比较器
,并根据条件提供比较器:

list.sortedWith(
    if (sortingOrder == WordSortingOrder.BY_ALPHA)
        compareBy { it.word.value }
    else
        compareBy { it.createdAt }
)
这里使用函数创建不同属性的比较器

然后,您可以将根据排序顺序选择比较器的逻辑提取到函数:

list.sortedWith(comparatorFor(sortingOrder))

fun comparatorFor(sortingOrder: WordSortingOrder): Comparator<MyType> = ...
list.sortedWith(comparatorFor(排序顺序))
有趣的比较器for(排序顺序:WordSortingOrder):比较器=。。。

对我来说,后一个代码显示了一个编译器错误:
推断类型Any不是Comparable
的子类型,我想这是因为
it.word.value
it.createdAt
有不同的返回类型,因为属性有不同的类型,在
Comparable
中需要将返回值强制转换为
Comparable
以避免编译器错误。随着铸造它看起来不再那么好了,所以可能有问题中的代码是一个更好的解决方案。它还允许轻松地在升序和降序之间切换。我以前没有考虑过。我添加了另一个使用
run
的示例。基本上,您可以将任何操作组包装在
let
run
块中,然后继续链接。