在Kotlin中按多个字段对集合进行排序

368

假设我有一个人员列表,我需要首先按年龄排序,然后再按姓名排序。

作为一个C#背景下的开发者,我可以很容易地使用LINQ来实现这一点:

var list=new List<Person>();
list.Add(new Person(25, "Tom"));
list.Add(new Person(25, "Dave"));
list.Add(new Person(20, "Kate"));
list.Add(new Person(20, "Alice"));

//will produce: Alice, Kate, Dave, Tom
var sortedList=list.OrderBy(person => person.Age).ThenBy(person => person.Name).ToList(); 

如何使用Kotlin实现这一点?

这是我尝试过的(显然是错误的,因为第一个“sortedBy”子句的输出会被第二个子句覆盖,导致仅按名称排序的列表)

val sortedList = ArrayList(list.sortedBy { it.age }.sortedBy { it.name })) //wrong

我也来自C#的世界,曾经有过同样的问题;感谢你提出了这个问题! - Dan Lugg
2个回答

639

sortedWith + compareBy(接受可变数量的lambda函数)可以解决这个问题:

val sortedList = list.sortedWith(compareBy({ it.age }, { it.name }))

您还可以使用更简洁的可调用引用语法:

val sortedList = list.sortedWith(compareBy(Person::age, Person::name))

1
在 Kotlin 1.2.42 中,这两个解决方案都会出现编译错误:“无法在不完成类型推断的情况下选择以下候选项:public fun <T> compareBy(vararg selectors: (???) → Comparable<>?): kotlin.Comparator<???> defined in kotlin.comparisons public fun <T> compareBy(vararg selectors: (T) → Comparable<*>?): kotlin.Comparator<T> / = java.util.Comparator<T> */ defined in kotlin.comparisons” - arslancharyev31
1
@arslancharyev31 这似乎被报告为一个 bug。它只在 IDE 中显示;我的 gradle build 成功了。 - Steven Jeuris
7
这是按升序排序,如何按降序排序? - Chandrika
11
@Chandrika compareByDescending - Alexander Udalov
67
compareByDescending 会翻转所有的函数。如果你只想使用一个字段进行降序排序,可以在前面加上 - (减号),例如 {-it.age}。请注意,本操作不改变原有意义,只是让语言更加通俗易懂。 - Abhijit Sarkar
显示剩余7条评论

219

使用sortedWith函数对列表进行排序,并传入Comparator参数。

你可以通过以下几种方式构建一个Comparator

  • compareBythenBy函数用于链式调用构建Comparator

    list.sortedWith(compareBy<Person> { it.age }.thenBy { it.name }.thenBy { it.address })
    
  • compareBy 有一个重载版本可以接受多个函数:

    list.sortedWith(compareBy({ it.age }, { it.name }, { it.address }))
    

1
谢谢,这正是我在寻找的!我对Kotlin还有点陌生,为什么你在第一条要点中需要使用compareBy<Person>而不是只用compareBy - ElectronAnt
2
@Aneem,Kotlin编译器有时无法推断类型参数,需要手动指定。其中一种情况是当期望通用类型并且您想要传递通用函数调用链的结果时,例如 compareBy<Person> { it.age }.thenBy { it.name }.thenBy { it.address }。在第二个点中,只有一个函数调用,没有调用链:compareBy({ it.age }, { it.name }, { it.address }) - hotkey
2
如何添加不区分大小写的功能? - K.Os
1
@KoustuvGanguly 或许这个链接可以帮到你 https://stackoverflow.com/questions/52284130/how-to-sort-list-of-objects-by-two-properties-and-collator - K.Os
@epool 您的链接显示一个空的游乐场。 - ASP
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接