Swift: видалення всіх елементів масиву


108

Я намагаюся видалити всі елементи масиву з циклу for на зразок цього:

for index 1...myArray.count {
   myArray.removeAtIndex(index)
}

Але це не працює, я отримую цю помилку перед тим, як згорнути:

Очікувано ';' в заяві "за"


5
Простий. повторно ініціалізувати масив ...
VJ

Відповіді:


326

Існує метод (власне функція)

myArray.removeAll()

1
Не знали про це, Дякую +1
JamesG

11
@NoodleOfDeath Строго говорять масиви Swift є structs, і структури мають functionsвідміну від класів, які мають methods.
вадіан

1
@vadian +1 для уточнення. Я забув Arrays є structs. Тут ветеран-об'єктив-C-кодер ...
NoodleOfDeath

1
чи потрібно викликати функцію RemoveAll () під час виходу з представлення (viewcontroller), де ви ініціалізуєте його, чи він проходить самостійно !?
Famic Tech

1
@FamicTech Це залежить: Якщо вигляд не завантажений, він відходить неявно, якщо подання лише зникає, вам потрібно зателефонувати removeAll(). Однак добре (дисциплінованість пам’яті) добре видаляти всі непотрібні дані, коли вид зникає.
вадіан

17

Приймаючи як належне, що відповідь @ vadian - це рішення , я просто хочу зазначити, що ваш код не працює.

Перш за все, індекси масиву базуються на 0, тому слід переписати діапазон відповідно:

for index 0..<myArray.count {
   myArray.removeAtIndex(index)
}

Однак ця реалізація спричинить збій. Якщо у вас є масив з 10 елементів, останній елемент займає позицію в індексі 9.

Використовуючи цей цикл, при першій ітерації елемент в індексі 0 видаляється, і це призводить до зміщення останнього елемента вниз на індекс 8.

При наступній ітерації елемент в індексі 1 видаляється, а останній елемент зміщується вниз на індекс 7. І так далі.

У якийсь момент циклу спроба видалити елемент із неіснуючого індексу призведе до збоїв програми.

Видаляючи елементи з масиву в циклі, найкращий спосіб зробити це шляхом обходу його в зворотному порядку:

for index in reverse(0..<myArray.count) {
    myArray.removeAtIndex(index)
}

Це забезпечує, що вилучені елементи не змінюють порядок або індекс елементів, які ще обробляються.


1
Існує функція видалення всіх елементів лише в одному рядку. як відповідь @ vadian ...
VJ

3
@VJ, це я написав у першому рядку своєї відповіді :)
Антоніо

+1 для рішення, яке можна використовувати для видалення певного екземпляра об'єкта. Я public extension Array where Element : Equatable { public mutating func remove(element: Element) -> Int { var occurrences = 0; for index in (0 ..< count).reverse() { if self[index] == element { removeAtIndex(index); occurrences += 1 } }; return occurrences } }бажано використовувати не весь один рядок, але цей код повинен збиратись в одному рядку
NoodleOfDeath

Чому ні for _ in 0...<myArray.count { myArray.removeAtIndex(0) }? Я ще не дуже знаю про ефективність, але таким чином вам не потрібно змінювати діапазон, тому, можливо, це швидше.
cbjeukendrup

Це теж працює! Цей же метод з точки зору ефективності ви видаляєте з початку замість кінця, але ви зберігаєте змінну :-)
Антоніо,

7

Вам не вистачає inключового слова, яке викликає вашу помилку. Код повинен бути:

for index in 1...myArray.count {
    myArray.removeAtIndex(index)
}

Однак це не спрацює, як ви очікували з кількох причин:

  • Останній дійсний індекс - це те, count - 1що потрібно1..<myArray.count
  • Ще важливіше видалення елемента з масиву скорочує його, таким чином змінюючи індекси щоразу.

Якщо ви намагаєтесь вилучити всі масиви з масиву, тоді ви повинні зробити так, як запропонували інші, і використовувати:

myArray.removeAll()

У випадку, якщо ви хочете лише перший елемент, і нічого іншого, ви можете отримати посилання на перший об'єкт, опустіть масив, а потім додайте об'єкт знову:

var firstElement = myArray.first!
myArray.removeAll()
myArray.append(firstElement)

Вибачте, що я не бачив "в" ... Зробив +1
VJ

1
(+1) для пояснення фактичної помилки. (-1), оскільки це не працюватиме, оскільки видалення елемента скорочує масив. (Зауважте також, що останній дійсний індекс count - 1).
Мартін Р.

7

Якщо ви дійсно хочете очистити масив, найпростіший спосіб - це повторно ініціалізувати його.


3

Ваш код повинен працювати, він просто не зв'язаний.

Швидкий 3

existingArray = []

Роблячи це, ви повторно присвоюєте порожній масив існуючому масиву, і тип даних передається.

Крім того, ви можете використовувати, removeAllщо видаляє всі елементи з масиву і надає можливість зберегти існуючу ємність.

existingArray.removeAll()

Це mutatingфункція, яка означає, що масив, що викликає метод, буде змінений (порожній).


2

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

Один із способів вирішити це - перерахувати назад. Швидко це робиться за допомогою кроків .

for index in stride(from: myArray.count - 1, through: 0, by: -1) {
    myArray.removeAtIndex(index)
}

інший варіант буде використовувати filter()

Швидкий 1.2

myArray = filter(myArray, { (obj) -> Bool in
    return false
})

Швидкий 2

myArray = myArray.filter{ (obj) -> Bool in
    return false
}

Дуже цікаво! Я не знав про цеstride
Кайл Деко

1

У Swift 2 доступний метод RemoveAllObjects ()

Syntax :  public func removeAllObjects()
Eg.:   mainArray.removeAllObjects

Для видалення елемента в конкретному індексі використовуйте:

Syntax : public func removeObjectAtIndex(index: Int)
Eg.: mainArray.removeObjectAtIndex(5)

Щоб видалити останній елемент, використовуйте:

Syntax : public func removeLastObject()
Eg.: mainArray.removeLastObject()

Для видалення елементів, зокрема в діапазоні, використовуйте:

Syntax : public func removeObject(anObject: AnyObject, inRange range: NSRange)

Для видалення конкретного елемента використовуйте:

Syntax : public func removeObject(anObject: AnyObject)

Нижче на скріншоті показаний список методів, доступних у розширенні NSMutableArray

Знімок екрана 1


0

Ви також можете зробити це:

for _ in myArray
{
    myArray.removeAtIndex(0)
}

2
Це рішення жахливо неефективне - на кожній ітерації зміщуються всі наступні об'єкти. Крім того, я не впевнений, чи безпечна ця реалізація. Принаймні, у колекціях Objective-C мутація під час перерахування заборонена.
Борис Веребський


0

У Вадіана є правильна відповідь з точки зору того, що ви намагаєтеся зробити. Проблема, яка відображається в результаті зразка вашого коду, пов'язана з тим, як ви намагаєтеся створити forцикл. Indexпочнеться за замовчуванням 0. Додавання діапазону чисел після не правильного способу створення циклу для циклу. Ось чому ви бачите помилку. Замість цього створіть свій цикл наступним чином:

for index in myArray.indices {
    // Do stuff
}

Сподіваємось, ця відповідь допоможе іншим, хто не знайомий із Swift чи програмуванням.


ви повинні використовувати властивість індексів масиву до під час ітерації колекції. Не всі колекції починаються з нульового індексу
Лео Дабус

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.