Ответ 1
В Swift 2 это довольно просто, используя enumerate
и reverse
.
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
a.removeAtIndex(i)
}
print(a)
Смотрите мой swiftstub здесь: http://swiftstub.com/944024718/?v=beta
Я хочу перечислить массив в Swift и удалить определенные элементы. Мне интересно, безопасно ли это делать, а если нет, то как я должен это достичь.
В настоящее время я буду делать это:
for (index, aString: String) in enumerate(array) {
//Some of the strings...
array.removeAtIndex(index)
}
В Swift 2 это довольно просто, используя enumerate
и reverse
.
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerate().reverse() {
a.removeAtIndex(i)
}
print(a)
Смотрите мой swiftstub здесь: http://swiftstub.com/944024718/?v=beta
Вы можете рассмотреть способ filter
:
var theStrings = ["foo", "bar", "zxy"]
// Filter only strings that begins with "b"
theStrings = theStrings.filter { $0.hasPrefix("b") }
Параметр filter
- это просто замыкание, которое принимает экземпляр типа массива (в данном случае String
) и возвращает a Bool
. Когда результат true
, он сохраняет элемент, иначе элемент отфильтровывается.
В Swift 3 и 4 это будет:
С цифрами, в соответствии с ответом Джонстона:
var a = [1,2,3,4,5,6]
for (i,num) in a.enumerated().reversed() {
a.remove(at: i)
}
print(a)
Со строками strings в качестве 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
.Когда элемент из определенного индекса удаляется из массива, все последующие элементы будут изменять свою позицию (и индекс), потому что они сдвигаются назад на одну позицию.
Итак, лучший способ - перемещаться по массиву в обратном порядке - и в этом случае я предлагаю использовать традиционный цикл for:
for var index = array.count - 1; index >= 0; --index {
if condition {
array.removeAtIndex(index)
}
}
Однако, на мой взгляд, лучший подход заключается в использовании метода filter
, как описано в его ответе @perlfly.
Нет, это небезопасно, чтобы мутировать массивы во время перезаписи, ваш код сработает.
Если вы хотите удалить только несколько объектов, вы можете использовать функцию filter
.
Либо создайте изменчивый массив для хранения элементов, которые нужно удалить, а затем, после перечисления, удалите эти элементы из оригинала. Или создайте копию массива (неизменяемый), перечислите это и удалите объекты (не по индексу) из оригинала при перечислении.
Я рекомендую установить элементы в nil во время перечисления и после завершения удалить все пустые элементы с помощью метода array() array().
Традиционный цикл for можно заменить простым циклом while, который полезен, если вам также необходимо выполнить некоторые другие операции с каждым элементом перед удалением.
var index = array.count-1
while index >= 0 {
let element = array[index]
//any operations on element
array.remove(at: index)
index -= 1
}