sorting - 如何在 Kotlin 中根据多种类型和值进行排序?

标签 sorting kotlin comparator comparable

给定以下类:

interface Item {
    val name: String
}

data class Server(override val name: String, val id: String) : Item
data class Local(override val name: String, val date: Int) : Item
data class Footer(override val name: String) : Item

如果我们创建一个列表:

val items = arrayListOf<Item>()
items.add(Server("server", "b"))
items.add(Local("local", 2))
items.add(Footer("footer"))
items.add(Server("server", "a"))
items.add(Local("local", 1))
items.add(Footer("footer"))
items.add(Server("server", "c"))
items.add(Local("local", 0))

然后排序:

val groupBy = items.groupBy { it.name }

val partialSort = arrayListOf<Item>()

//individually sort each type
partialSort.addAll(groupBy["local"]!!.map { it as Local }.sortedWith(compareBy({ it.date })))
partialSort.addAll(groupBy["server"]!!.map { it as Server }.sortedWith(compareBy({ it.id })))
partialSort.addAll(groupBy["footer"]!!.map { it as Footer })

//this can be avoided if above three lines are rearranged
val fullSort = partialSort.sortedWith(compareBy({ it is Footer }, { it is Local }, { it is Server }))

然后我得到一个列表,如果它是通过以下注释代码创建的:

//        items.add(Server("server", "a"))
//        items.add(Server("server", "b"))
//        items.add(Server("server", "c"))
//        items.add(Local("local", 0))
//        items.add(Local("local", 1))
//        items.add(Local("local", 2))
//        items.add(Footer("footer"))
//        items.add(Footer("footer"))

有没有更好的方法来对它进行排序? 我读了How to sort based on/compare multiple values in Kotlin?Sort collection by multiple fields in Kotlin已经但无法将其应用于我的代码。

最佳答案

是的,它可以在单个操作中实现(但非常复杂),并且您的想法是正确的,compareBy 可以为您解决问题

items.sortWith(compareBy({
    when (it) {
        is Server -> -1
        is Local -> 0
        is Footer -> 1
        else -> Integer.MAX_VALUE
    }
}, {
    when (it) {
        is Server -> it.id
        is Local -> it.date
        else -> 0
    }
}))

我们在这里做什么:

  1. 我们正在为 Item 的实现创建综合比较器。当然,如果这是常见的用例,这个数字可能只是界面中的另一个字段。
  2. 我们正在定义要在 ServerLocal 上进行比较的字段,因为它们具有额外的排序标准。
  3. 我们将在第 1 步和第 2 步中创建的比较器传递给 compareBy 函数。

在这个操作之后items集合被排序:

[Server(name=server, id=a), Server(name=server, id=b), Server(name=server, id=c), Local(name=local, date=0), Local(name=local, date=1), Local(name=local, date=2), Footer(name=footer), Footer(name=footer)]

UPD:如果 Item 的名称也应该成为排序的对象 - 您可以轻松地在其中添加一个比较器,例如 Item::name合适的地方。

关于sorting - 如何在 Kotlin 中根据多种类型和值进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49460724/

相关文章:

c++ - C++ wrt 字符串中的 STL 排序函数

android - 用于测试 rxjava 的书面单元测试,但不确定我的单元测试是否正在测试所有内容

java - 如何使用 Function<T, U> 将 Comparator<T> 映射到 Comparator<U>?

java - 尝试在 Java 中使用自定义比较器时出错

c++ - C++ 中各种自定义比较器函数之间的差异

java - 按代码排序

java - 使用 Glazed Lists 和 JXTable 进行表外列排序

php - MYSQL:选择按字母顺序排序的父项与按字母顺序排序的子项分组

java - Java翻译成 "private lateinit var lookupKey: String"是什么

maven - Kotlin-无法在intellij中运行 “hello world”