Я хочу перечислить массив в Swift и удалить определенные элементы. Мне интересно, безопасно ли это делать, а если нет, то как я должен этого добиться.
В настоящее время я бы сделал это:
for (index, aString: String) in enumerate(array) {
//Some of the strings...
array.removeAtIndex(index)
}
ios
arrays
swift
enumeration
Андрей
источник
источник
filter
возвращает новый массив. Вы ничего не удаляете из массива. Я бы даже не стал называтьfilter
перечисление. Всегда есть несколько способов снять шкуру с кошки.Вы можете рассмотреть
filter
способ:var theStrings = ["foo", "bar", "zxy"] // Filter only strings that begins with "b" theStrings = theStrings.filter { $0.hasPrefix("b") }
Параметр
filter
- это просто замыкание, которое принимает экземпляр типа массива (в данном случаеString
) и возвращаетBool
. Когда в результатеtrue
он сохраняет элемент, в противном случае элемент отфильтровывается.источник
filter
не обновляет массив, а просто возвращает новыйfilter
метод вmutating
один (поскольку я читал, чтоmutating
ключевое слово позволяетself
вместо этого изменять такие функции )?Array
пометив его какmutating
и аналогичный коду вопроса. В любом случае учтите, что это не всегда может быть преимуществом. В любом случае каждый раз, когда вы удаляете объект, ваш массив может быть реорганизован в памяти. Таким образом, было бы более эффективно выделить новый массив и затем выполнить атомарную замену результатом функции фильтрации. Компилятор может сделать еще больше оптимизаций, в зависимости от вашего кода.В Swift 3 и 4 это будет:
С числами, согласно ответу Джонстона:
var a = [1,2,3,4,5,6] for (i,num) in a.enumerated().reversed() { a.remove(at: i) } print(a)
Со строками в качестве вопроса OP:
var b = ["a", "b", "c", "d", "e", "f"] for (i,str) in b.enumerated().reversed() { if str == "c" { b.remove(at: i) } } print(b)
Однако теперь в Swift 4.2 или новее есть даже лучший и более быстрый способ , рекомендованный Apple в WWDC2018:
var c = ["a", "b", "c", "d", "e", "f"] c.removeAll(where: {$0 == "c"}) print(c)
Этот новый способ имеет несколько преимуществ:
filter
.источник
{$0 === Class.self}
не работаетКогда элемент с определенным индексом удаляется из массива, все последующие элементы изменят свою позицию (и индекс), потому что они сдвигаются назад на одну позицию.
Итак, лучший способ - перемещаться по массиву в обратном порядке - и в этом случае я предлагаю использовать традиционный цикл for:
for var index = array.count - 1; index >= 0; --index { if condition { array.removeAtIndex(index) } }
Однако, на мой взгляд, лучший подход - использовать
filter
метод, описанный @perlfly в его ответе.источник
Нет, изменять массивы во время перечисления небезопасно, код выйдет из строя.
Если вы хотите удалить только несколько объектов, вы можете использовать эту
filter
функцию.источник
filter
является более безопасным . Вот мой глупый пример:var y = [1, 2, 3, 4, 5]; print(y); for (index, value) in y.enumerated() { y.remove(at: index) } print(y)
Либо создайте изменяемый массив для хранения элементов, которые нужно удалить, а затем, после перечисления, удалите эти элементы из оригинала. Или создайте копию массива (неизменяемую), перечислите ее и удалите объекты (не по индексу) из оригинала при перечислении.
источник
Традиционный цикл for можно заменить простым циклом while, который полезен, если вам также необходимо выполнить некоторые другие операции с каждым элементом перед удалением.
var index = array.count-1 while index >= 0 { let element = array[index] //any operations on element array.remove(at: index) index -= 1 }
источник
Я рекомендую установить для элементов значение nil во время перечисления, а после завершения удалить все пустые элементы с помощью метода массивов filter ().
источник
filter
метод не удаляет, а генерирует новый массив.Чтобы добавить, если у вас есть несколько массивов, и каждый элемент в индексе N массива A связан с индексом N массива B, вы все равно можете использовать метод, обращающий нумерованный массив (как в прошлых ответах). Но помните, что при доступе к элементам других массивов и их удалении не нужно их отменять.
Like so, (one can copy and paste this on Playground) var a = ["a", "b", "c", "d"] var b = [1, 2, 3, 4] var c = ["!", "@", "#", "$"] // remove c, 3, # for (index, ch) in a.enumerated().reversed() { print("CH: \(ch). INDEX: \(index) | b: \(b[index]) | c: \(c[index])") if ch == "c" { a.remove(at: index) b.remove(at: index) c.remove(at: index) } } print("-----") print(a) // ["a", "b", "d"] print(b) // [1, 2, 4] print(c) // ["!", "@", "$"]
источник