Сортировка
Порядок элементов является важным аспектом определенных типов коллекций. Например, два списка с одинаковыми элементами не равны, если их элементы упорядочены по-разному.
В Kotlin порядок объектов можно определить несколькими способами.
Во-первых, существует естественный порядок. Он определен для реализаций интерфейса Comparable. Естественный порядок используется для сортировки при отсутствии другого указанного порядка.
Большинство встроенных типов сопоставимы:
Числовые типы используют традиционный числовой порядок:
1больше, чем0;-3.4fбольше, чем-5f, и так далее.CharиStringиспользуют лексикографический порядок:bбольше, чемa;worldбольше, чемhello.
Для определения естественного порядка для пользовательского типа сделайте тип реализацией интерфейса Comparable. Это требует реализации функции compareTo(). compareTo() должна принять другой объект того же типа в качестве аргумента и вернуть целое число, показывающее, какой объект больше:
Положительные значения показывают, что объект-получатель больше.
Отрицательные значения показывают, что он меньше аргумента.
Ноль показывает, что объекты равны.
Ниже приведен класс для сортировки версий, состоящих из основной и дополнительной части.
class Version(val major: Int, val minor: Int): Comparable<Version> {
override fun compareTo(other: Version): Int = when {
this.major != other.major -> this.major compareTo other.major // compareTo() in the infix form
this.minor != other.minor -> this.minor compareTo other.minor
else -> 0
}
}
fun main() {
println(Version(1, 2) > Version(1, 3))
println(Version(2, 0) > Version(1, 5))
}
Пользовательский порядок позволяет сортировать экземпляры любого типа так, как вам нужно. В частности, вы можете определить порядок для несопоставимых объектов или определить порядок, отличный от естественного, для сопоставимого типа. Для определения пользовательского порядка для типа создайте Comparator для него. Comparator содержит функцию compare(): она принимает два экземпляра класса и возвращает целочисленный результат сравнения между ними. Результат интерпретируется так же, как результат compareTo(), как описано выше.
fun main() {
//sampleStart
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
//sampleEnd
}
Имея lengthComparator, вы можете упорядочивать строки по их длине вместо лексикографического порядка по умолчанию.
Более короткий способ определить Comparator - это функция compareBy() из стандартной библиотеки. compareBy() принимает лямбда-функцию, которая генерирует значение Comparable из экземпляра и определяет пользовательский порядок как естественный порядок сгенерированных значений.
С помощью compareBy(), компаратор длины из приведенного выше примера выглядит так:
fun main() {
//sampleStart
println(listOf("aaa", "bb", "c").sortedWith(compareBy { it.length }))
//sampleEnd
}
Пакет Kotlin collections предоставляет функции для сортировки коллекций в естественном, пользовательском и даже случайном порядке. На этой странице мы опишем функции сортировки, которые применяются к только для чтения коллекциям. Эти функции возвращают результат в виде новой коллекции, содержащей элементы исходной коллекции в запрошенном порядке. Чтобы узнать о функциях сортировки изменяемых коллекций на месте, см. операции, специфичные для списка.
Естественный порядок
Основные функции sorted() и sortedDescending() возвращают элементы коллекции, отсортированные в возрастающей и убывающей последовательности в соответствии с их естественным порядком. Эти функции применяются к коллекциям элементов Comparable.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four")
println("Sorted ascending: ${numbers.sorted()}")
println("Sorted descending: ${numbers.sortedDescending()}")
//sampleEnd
}
Пользовательские порядки
Для сортировки в пользовательских порядках или сортировки несопоставимых объектов существуют функции sortedBy() и sortedByDescending(). Они принимают функцию-селектор, которая отображает элементы коллекции в значения Comparable и сортирует коллекцию в естественном порядке этих значений.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four")
val sortedNumbers = numbers.sortedBy { it.length }
println("Sorted by length ascending: $sortedNumbers")
val sortedByLast = numbers.sortedByDescending { it.last() }
println("Sorted by the last letter descending: $sortedByLast")
//sampleEnd
}
Для определения пользовательского порядка сортировки коллекции вы можете предоставить собственный Comparator. Для этого вызовите функцию sortedWith(), передав в нее ваш Comparator. С помощью этой функции сортировка строк по длине выглядит так:
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four")
println("Sorted by length ascending: ${numbers.sortedWith(compareBy { it.length })}")
//sampleEnd
}
Обратный порядок
Вы можете получить коллекцию в обратном порядке, используя функцию reversed().
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four")
println(numbers.reversed())
//sampleEnd
}
reversed() возвращает новую коллекцию с копиями элементов. Таким образом, если вы измените исходную коллекцию позже, это не повлияет на ранее полученные результаты reversed().
Другая функция обратной перестановки - asReversed()
возвращает обращенный вид того же экземпляра коллекции, поэтому он может быть более легким и предпочтительным по сравнению с
reversed()если исходный список не будет изменяться.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four")
val reversedNumbers = numbers.asReversed()
println(reversedNumbers)
//sampleEnd
}
Если исходный список изменяемый, все его изменения отражаются в его обращенных представлениях и наоборот.
fun main() {
//sampleStart
val numbers = mutableListOf("one", "two", "three", "four")
val reversedNumbers = numbers.asReversed()
println(reversedNumbers)
numbers.add("five")
println(reversedNumbers)
//sampleEnd
}
Однако, если изменчивость списка неизвестна или источник вообще не является списком, reversed() предпочтительнее, поскольку его результат представляет собой копию, которая не изменится в будущем.
Случайный порядок
Наконец, есть функция, которая возвращает новую List , содержащую элементы коллекции в случайном порядке - shuffled(). Вы можете вызвать ее без аргументов или с объектом Random.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four")
println(numbers.shuffled())
//sampleEnd
}
© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/collection-ordering.html