我想从特定位置迭代一组项目。 假设我们要从中心开始,并迭代数组的整个右侧部分:
int startFrom = arr.length / 2;
for (int i = startFrom; i < arr.length; i++)
{
String.format("Index %d value %s", i, arr[i]);
}
在迭代过程中跟踪真实的索引和值很重要。例如,您将要实现就地排序算法
我尝试使用drop()。withIndexes()这样做,但是好像drop()创建了一个新集合,并且我丢失了有关真实索引的信息。 如果我们创建变量并计算适当的索引,则可以手动修复
val startFrom = inputData.size / 2
for ((i, item) in inputData.drop(startFrom).withIndex()){
val fixedIndex = i + startFrom
println("Index $i, fixed index $fixedIndex value $item")
}
此解决方案有效,但我希望有一些方法可以避免引入单独的fixedIndex变量并手动处理此问题。
答案 0 :(得分:3)
您的原始尝试非常接近,只需稍作更改即可使其生效。颠倒withIndex()
和drop(N)
的调用,将withIndex
放在第一位。
如果不想要复制该集合,则可以先使用asSequence()
将其转换为序列。
for ((index, item) in inputData.asSequence().withIndex().drop(startFrom)) { ... }
测试代码:
val sampleData = listOf("a", "b", "c", "d", "e", "f")
val startFrom = sampleData.size / 2
for ((index, item) in sampleData.asSequence().withIndex().drop(startFrom)) {
println("[$index] => $item")
}
输出:
[3] => d
[4] => e
[5] => f
就是这样!该答案的其余部分仅为您提供替代方案,包括在最后创建自己的扩展功能的更有效和Kotlinesque解决方案。
如果可以接受收藏集的副本,则可以执行以下简短版本。 withIndex
不会导致复制,但是drop(N)
会导致复制。
for ((index, item) in inputData.withIndex().drop(startFrom)) { ... }
热切复制或的顺序可能更快,这取决于集合的大小,运行时环境和CPU缓存。
您也可以使用功能性forEach
代替for
循环。
sampleData.asSequence().withIndex().drop(startFrom).forEach { (index, item) ->
println("[$index] => $item")
}
这将带来最佳,最有效的选择。只需在使用Array
或List
时编写扩展函数,就可以避免使用包装器类进行延迟评估也没有任何复制。只是一个循环,使用索引和值调用您的lambda。这是两个新的扩展名,它们添加了forEachIndexed
的新变体:
inline fun <T> Array<T>.forEachIndexed(startFrom: Int,
action: (index: Int, item: T)->Unit) {
for (i in startFrom until this.size) {
action(i, this[i])
}
}
inline fun <T> List<T>.forEachIndexed(startFrom: Int,
action: (index: Int, item: T)->Unit) {
for (i in startFrom until this.size) {
action(i, this[i])
}
}
这可以简单地用于任何非原始数组或列表:
sampleData.forEachIndexed(startFrom) { index, item ->
println("[$index] => $item")
}
如果您也想使用withIndex(startFrom)
样式方法,也可以执行相同的操作。您可以随时扩展Kotlin来获得想要的东西!
答案 1 :(得分:1)
如果这是您所缺少的,我认为最简单的解决方案是只使用一个有范围的for
循环:
val startFrom = arr.size / 2;
for (i in startFrom until arr.size) {
println(String.format("Index %d value %s", i, arr[i]));
}
如果您希望严格避免使用诸如arr[i]
之类的表达式,则可以将当前解决方案更改为使用序列。