@Juliann

Как работает array.indices?

Я только начала учить котлин и не могу понять, почему цикл пропускает 3.

val numbers = intArrayOf(1, 2, 3, 4, 5)
for(index in numbers.indices - 2) {
    println(numbers[index])
}

// 1 2 4 5
  • Вопрос задан
  • 249 просмотров
Решения вопроса 1
Casper-SC
@Casper-SC
Программист (.NET)
Удалился индекс 2, то есть элемент коллекции под индексом 2.
index: 0: value: 1
index: 1: value: 2
index: 2: value: 3
index: 3: value: 4
index: 4: value: 5

Если удалить индекс 2, то элемент 3 выведен не будет. Кажется логичным.

Я открыл IntelliJ IDEA, зажал Ctrl (Cmd в MacOS) и нажал левой кнопкой мыши на знак - (минус). Попал в метод-расширение minus. Скопировал его и другие связанные методы. Получил точно такое же поведение (потому что фактически выполняется тот же самый код). Теперь можно начать отлаживать код, пройтись по методам пошагово и понять почему мы имеем такой результат. Ранее упомянутый метод minus - это метод, которого нет в исходном классе Iterable<T>, но его добавили в какой-то библиотеке. Это не новшество Kotlin, такие же методы-расширения можно создавать, например, в C#.

623f0a3e1643d280918242.png

fun main(args: Array<String>) {

    val numbers = intArrayOf(1, 2, 3, 4, 5)

    // Исходный пример
    for (index in numbers.indices - 2) {
        println("index: $index: value: ${numbers[index]}")
    }

    println("------")

    // Пример-объяснение. Были взяты оригинальные методы расширения
    // и вынесены сюда для удобства отладки и наглядности.
    for (index in minus(numbers.indices, 2)) {
        println("index: $index: value: ${numbers[index]}")
    }
}

fun <T> minus(iterable: Iterable<T>, element: T): List<T> {
    val arraySize = collectionSizeOrDefault(iterable, 10)
    val result = ArrayList<T>(arraySize)
    var removed = false
    return filterTo(iterable, result) {
        if (!removed && it == element) {
            removed = true; false
        } else true
    }
}

fun <T> collectionSizeOrDefault(iterable: Iterable<T>, default: Int): Int =
    if (iterable is Collection<*>) iterable.size else default

fun <T, C : MutableCollection<in T>> filterTo(iterable: Iterable<T>, destination: C, predicate: (T) -> Boolean): C {
    for (element in iterable) if (predicate(element)) destination.add(element)
    return destination
}


Лучше вынести из выражение, чтобы удобнее было дебажить и смотреть, что там к чему:
val result: List<Int> = minus(numbers.indices, 2)
    for (index in result) {
        println("index: $index: value: ${numbers[index]}")
    }


Вывод:
index: 0: value: 1
index: 1: value: 2
index: 3: value: 4
index: 4: value: 5
------
index: 0: value: 1
index: 1: value: 2
index: 3: value: 4
index: 4: value: 5
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы