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.