Получение частей коллекции
Стандартная библиотека Kotlin содержит функции расширения для извлечения частей коллекции. Эти функции предоставляют различные способы выбора элементов для результирующей коллекции: явное указание их позиций, указание размера результата и другие.
Вырезка (Slice)
slice() возвращает список элементов коллекции с заданными индексами. Индексы можно передать либо в виде диапазона, либо в виде коллекции целых значений.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.slice(1..3))
println(numbers.slice(0..4 step 2))
println(numbers.slice(setOf(3, 5, 0)))
//sampleEnd
}
Взятие и удаление (Take and drop)
Чтобы получить заданное количество элементов, начиная с первого, используйте функцию take(). Для получения последних элементов используйте takeLast(). Если функция вызывается с числом, большим, чем размер коллекции, обе функции возвращают всю коллекцию.
Чтобы взять все элементы, кроме заданного количества первых или последних элементов, вызовите функции drop() и dropLast() соответственно.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.take(3))
println(numbers.takeLast(3))
println(numbers.drop(1))
println(numbers.dropLast(5))
//sampleEnd
}
Вы также можете использовать предикаты для определения количества элементов для взятия или удаления. Существуют четыре функции, аналогичные описанным выше:
takeWhile()аналогичнаtake(), но с предикатом: она берёт элементы до, но не включая, первого элемента, не соответствующего предикату. Если первый элемент коллекции не соответствует предикату, результат пуст.takeLastWhile()аналогичнаtakeLast(): она берёт диапазон элементов, соответствующих предикату, с конца коллекции. Первый элемент диапазона — элемент, следующий за последним элементом, не соответствующим предикату. Если последний элемент коллекции не соответствует предикату, результат пуст;dropWhile()— это противоположностьtakeWhile()с тем же предикатом: она возвращает элементы от первого элемента, не соответствующего предикату, до конца.dropLastWhile()— это противоположностьtakeLastWhile()с тем же предикатом: она возвращает элементы с начала до последнего элемента, не соответствующего предикату.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.takeWhile { !it.startsWith('f') })
println(numbers.takeLastWhile { it != "three" })
println(numbers.dropWhile { it.length == 3 })
println(numbers.dropLastWhile { it.contains('i') })
//sampleEnd
}
Разбиение на блоки (Chunked)
Чтобы разбить коллекцию на части заданного размера, используйте функцию chunked(). chunked() принимает единственный аргумент — размер блока — и возвращает коллекцию списков заданного размера. Первый блок начинается с первого элемента и содержит size элементов, второй блок содержит следующие size элементов и так далее. Последний блок может иметь меньший размер.
fun main() {
//sampleStart
val numbers = (0..13).toList()
println(numbers.chunked(3))
//sampleEnd
}
Вы также можете применить преобразование к возвращаемым блокам сразу. Для этого укажите преобразование в качестве лямбда-функции при вызове chunked(). Аргументом лямбда-функции является блок коллекции. При вызове chunked() с преобразованием блоки являются кратковременными List объектами, которые следует потреблять непосредственно в этой лямбда-функции.
fun main() {
//sampleStart
val numbers = (0..13).toList()
println(numbers.chunked(3) { it.sum() }) // `it` is a chunk of the original collection
//sampleEnd
}
Окна (Windowed)
Вы можете получить все возможные диапазоны элементов коллекции заданного размера. Функция для получения этих диапазонов называется windowed(): она возвращает список диапазонов элементов, которые вы бы увидели, если бы смотрели на коллекцию через скользящее окно заданного размера. В отличие от chunked(), windowed() возвращает диапазоны элементов (окна) начиная с каждого элемента коллекции. Все окна возвращаются как элементы одного списка List.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.windowed(3))
//sampleEnd
}
windowed() предоставляет больше гибкости с необязательными параметрами:
stepопределяет расстояние между первыми элементами двух соседних окон. По умолчанию значение равно 1, поэтому результат содержит окна, начинающиеся со всех элементов. Если вы увеличите шаг до 2, вы получите только окна, начинающиеся с нечётных элементов: первого, третьего и так далее.partialWindowsвключает окна меньшего размера, начинающиеся с элементов в конце коллекции. Например, если вы запрашиваете окна из трёх элементов, вы не можете создать их для последних двух элементов. ВключениеpartialWindowsв этом случае включает два дополнительных списка размеров 2 и 1.
Наконец, вы можете применить преобразование к возвращаемым диапазонам сразу. Для этого укажите преобразование в качестве лямбда-функции при вызове windowed().
fun main() {
//sampleStart
val numbers = (1..10).toList()
println(numbers.windowed(3, step = 2, partialWindows = true))
println(numbers.windowed(3) { it.sum() })
//sampleEnd
}
Для создания окон из двух элементов существует отдельная функция — zipWithNext(). Она создаёт пары соседних элементов получаемой коллекции. Обратите внимание, что zipWithNext() не разбивает коллекцию на пары; она создаёт пару для каждого элемента, кроме последнего, поэтому её результат для [1, 2, 3, 4] равен [[1, 2], [2, 3], [3, 4]], а не [[1, 2], [3, 4]]. zipWithNext() также можно вызвать с функцией преобразования; она должна принимать два элемента получаемой коллекции в качестве аргументов.
fun main() {
//sampleStart
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.zipWithNext())
println(numbers.zipWithNext() { s1, s2 -> s1.length > s2.length})
//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-parts.html