Котлин: Как перебрать коллекцию из определенной позиции с индексами (пропустить N элементов с индексами) - PullRequest
0 голосов
/ 21 мая 2019

Я хочу перебрать коллекцию предметов с определенной позиции.Допустим, мы хотим начать с центра и выполнить итерацию всей правой части массива:

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 и решения этой проблемы вручную.

Ответы [ 2 ]

3 голосов
/ 21 мая 2019

Ваша первоначальная попытка очень близка, только небольшое изменение заставляет ее работать.Отмените вызовы 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] => е[5] => f

Вот и все!Остальная часть этого ответа просто предоставляет вам альтернативы, в том числе более эффективное и Kotlinesque решение создания вашей собственной функции расширения в конце.

Если копия коллекции приемлема, вы можете сделать следующую более короткую версию.withIndex не вызывает копию, но drop(N) делает.

for ((index, item) in inputData.withIndex().drop(startFrom)) { ... }

Стремительная копия или последовательность может быть быстрее, это зависит от размера коллекции, среда выполнения и кэш-память ЦП.

Вы также можете использовать функциональный forEach вместо цикла for.

sampleData.asSequence().withIndex().drop(startFrom).forEach { (index, item) ->
    println("[$index] => $item")       
}

Какойзатем выводит лучший и наиболее эффективный вариант. Просто напишите функцию расширения при использовании Array или List, чтобы не было ленивых вычислений с использованием классов-оберток или какого-либо копирования.Просто цикл, вызывающий вашу лямбду с индексом и значением.Вот два новых расширения, которые добавляют новый вариант 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")
}

Youможет сделать то же самое, если вы хотите метод стиля withIndex(startFrom).Вы всегда можете расширить Kotlin, чтобы получить то, что вы хотите!

1 голос
/ 21 мая 2019

Если это то, что вам не хватает, самое простое решение, на мой взгляд, это просто использовать дальний цикл 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], тогда вы можете изменить текущее решение, чтобы использовать вместо него последовательность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...