在本主题中,我们将探索一些 Kotlin 方法,这些方法可以让你更轻松地获取集合中的元素,从而帮助你更高效地操作集合。
切片 是一个基本操作:它根据索引返回集合中某个范围的元素。
如果你使用 slice()
方法,就可以根据索引范围或具体的索引集合获取一个新的集合。返回的是一个新集合,包含给定索引处的元素。
fun main() {
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 使用切片和范围获取第 1 到第 5 个元素
println(list.slice(0..4)) // 输出:[1, 2, 3, 4, 5]
// 使用范围和步长获取第 1 到第 5 个元素(间隔为2)
println(list.slice(0..5 step 2)) // 输出:[1, 3, 5]
// 使用倒序和步长获取第 5 到第 1 个元素
println(list.slice(4 downTo 0 step 2)) // 输出:[5, 3, 1]
// 使用指定索引集合获取元素
println(list.slice(listOf(0, 2, 4))) // 输出:[1, 3, 5]
}
有时你想获取集合的元素但又不想使用索引。这时就可以使用 take
系列方法:
take(n)
:从集合开始位置起获取前 n 个元素,如果 n 超出集合长度,则返回整个集合。
takeLast(n)
:从集合末尾获取最后 n 个元素。
takeWhile { 条件 }
:从第一个元素开始,持续获取满足条件的元素,直到遇到第一个不满足条件的元素为止。
takeLastWhile { 条件 }
:从最后一个元素开始,持续获取满足条件的元素,直到遇到第一个不满足条件的元素为止。
fun main() {
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println(list.take(5)) // [1, 2, 3, 4, 5]
println(list.takeLast(5)) // [6, 7, 8, 9, 10]
println(list.takeWhile { it < 5 }) // [1, 2, 3, 4]
println(list.takeLastWhile { it > 5 }) // [6, 7, 8, 9, 10]
}
对应地,也有 drop
系列方法,它们用于跳过元素:
drop(n)
:跳过前 n 个元素,返回剩下的。
dropLast(n)
:跳过最后 n 个元素,返回剩下的。
dropWhile { 条件 }
:从第一个元素开始,跳过所有满足条件的元素,直到遇到不满足条件的第一个元素为止。
dropLastWhile { 条件 }
:从最后一个元素开始,跳过所有满足条件的元素,直到遇到不满足条件的第一个元素为止。
fun main() {
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println(list.drop(5)) // [6, 7, 8, 9, 10]
println(list.dropLast(5)) // [1, 2, 3, 4, 5]
println(list.dropWhile { it < 5 }) // [5, 6, 7, 8, 9, 10]
println(list.dropLastWhile { it > 5 })// [1, 2, 3, 4, 5]
}
在实际开发中,我们经常需要将集合划分为固定大小的部分。chunked()
方法就是用来实现这种划分的。
该函数接收一个整数参数表示块的大小,并返回一个由列表组成的列表,每个子列表的大小为指定值。如果最后一组不足块大小,也会照样返回。
你还可以传入一个 lambda 表达式对每个块进行转换。
fun main() {
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 每3个为一组进行分块
println(list.chunked(3))
// 输出:[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
// 每3个为一组,将每组求和
println(list.chunked(3) { it.sum() })
// 输出:[6, 15, 24, 10]
// 每3个为一组,将每组转换成字符串
println(list.chunked(3) { it.joinToString() })
// 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
你还可以通过 windowed()
函数从集合中获取所有可能的固定大小子区间(窗口),相比 chunked()
,这个函数更灵活。
参数说明:
size
:窗口大小,即每个子列表的元素个数。
step
:滑动步长,表示每个窗口之间第一个元素的间隔,默认为1。
partialWindows
:是否保留末尾不足窗口大小的子集,默认为 false。
你也可以传入 lambda 表达式对每个窗口进行处理。
fun main() {
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 窗口大小为3,步长为1(默认)
println(list.windowed(3))
// 输出:[[1, 2, 3], [2, 3, 4], ..., [8, 9, 10]]
// 窗口大小为3,步长为3
println(list.windowed(3, 3))
// 输出:[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 步长为4,partialWindows = false
println(list.windowed(3, 4, false))
// 输出:[[1, 2, 3], [5, 6, 7]]
// 步长为4,partialWindows = true
println(list.windowed(3, 4, true))
// 输出:[[1, 2, 3], [5, 6, 7], [9, 10]]
// 窗口求和
println(list.windowed(3, 4, true) { it.sum() })
// 输出:[6, 18, 19]
}
在本主题中,你学习了几种从集合中获取元素的方法:
使用 slice()
根据索引提取元素;
使用 take()
获取前 n 个元素;
使用 drop()
跳过前 n 个元素;
使用 chunked()
将集合分成固定大小的部分;
使用 windowed()
滑动地提取子集合。