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

    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
    Ответ написан
    1 комментарий