Arhn - архитектура программирования

Как безопасно удалить элементы из массива в цикле for?

Полное раскрытие, это вопрос домашнего задания:

Он должен иметь частное свойство типа [Circle]. Массив кругов. Метод должен удалять любые круги, радиус которых больше минимального требования и меньше максимального требования.

Кажется очевидным, что я должен использовать removeAtIndex() для удаления элементов массива, которые не соответствуют условию, определенному в цикле. Тем не менее, многие указывали на опасность удаления элементов в цикле из-за того, что я предполагаю, это «несоответствие итератора/индекса».

В конечном итоге я создал пустой массив и использовал .append() для передачи значений, соответствующих "хорошему" условию, в массив filteredCircles, но я не могу не чувствовать, что это не соответствует критериям для назначения.

Есть ли решение, которое фактически удаляет элементы из массива в цикле?

30.01.2016

  • Начните с последнего индекса и повторяйте цикл, пока не дойдете до первого. Удаление элементов влияет только на индексы следующих за ними элементов. 30.01.2016
  • @vacawama Как мне это сделать в Swift? синтаксис цикла не позволяет использовать индекс, как и в других языках, поэтому я не знаю, как считать в обратном порядке. 30.01.2016
  • @vacawama Nm... только что узнал о circles.enumerate().reverse(). Благодарю вас! 30.01.2016
  • Взгляните на Удалить совпадающий элемент из массива объектов?. 30.01.2016

Ответы:


1

Если FOR LOOP не является обязательным (и я не вижу этого требования в цитируемом тексте), вам следует использовать метод filter.

Когда вы вызываете filter для массива, вы получаете новый массив, содержащий только значения, соответствующие замыканию, которое вы передали filter. Исходный массив не изменен.

struct Circle {
    let radius: Double
}

let circles = [Circle(radius: 1), Circle(radius: 5.1), Circle(radius: 4), Circle(radius: 10.8)]

let bigCircles = circles.filter { $0.radius > 5 }

Почему этот подход лучше, чем изменение массива в цикле FOR

  1. Поскольку circles является константой, у вас не возникает проблем, связанных с многопоточным программированием. Если бы circles был изменяемым, то другие потоки могли бы изменить его, пока вы зацикливаете его с очень страшными побочными эффектами.
  2. Он менее подвержен ошибкам. Вы не пишете, что должен делать ЦП, вместо этого вы описываете, какими должны быть результаты. Так что меньше потенциальных недоразумений между вами и компилятором :)
  3. Вы пишете меньше кода, что означает меньше потенциальных ошибок.

Вот некоторые из преимуществ написания кода функционального программирования.

30.01.2016
  • Думаю, мне следует просто попробовать, но действительно ли .filter изменяет массив? 30.01.2016
  • нет. вот почему он присвоил возвращаемое значение переменной круга (которую нужно было бы объявить с помощью var) 30.01.2016
  • @nipponese: Нет, не так. И это хорошо, потому что (по нескольким причинам) circles должно быть константой. Но если вы хотите, вы можете сделать circle var и переназначить результат той же переменной. 30.01.2016

  • 2

    Чтобы уточнить ответ @vacawama:

    struct Circle {
        var radius: Int
    }
    
    struct MyStruct {
        private var circles: [Circle]
    
        mutating func removeCirclesWithRadiusWithin(range: Range<Int>) {
            for index in (circles.startIndex..<circles.endIndex).reverse() {
                if range.contains(circles[index].radius) {
                    circles.removeAtIndex(index)
                }
            }
        }
    }
    

    Если вы хотите использовать Double для radius ваших Circle, но хотите сохранить приятный синтаксис:

    struct Circle {
        var radius: Double
    }
    
    struct MyStruct {
        private var circles: [Circle]
    
        mutating func removeCirclesWithRadiusWithin<I: IntervalType where I.Bound == Double>(interval: I) {
            for index in (circles.startIndex..<circles.endIndex).reverse() {
                if interval.contains(circles[index].radius) {
                    circles.removeAtIndex(index)
                }
            }
        }
    }
    
    30.01.2016
  • Поскольку вы изменяете содержимое сохраненного свойства внутри структуры. Поэтому, если вы объявили экземпляр MyStruct с помощью let, вы не смогли бы использовать этот метод. 30.01.2016
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..