Як видалити елемент із масиву в Swift


236

Як я можу зняти / видалити елемент із масиву в новій мові Swift від Apple?

Ось код:

let animals = ["cats", "dogs", "chimps", "moose"]

Як елемент animals[2]можна було видалити з масиву?

Відповіді:


300

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

var animals = ["cats", "dogs", "chimps", "moose"]

animals.remove(at: 2)  //["cats", "dogs", "moose"]

Немутуюча альтернатива, яка збереже оригінальну колекцію незмінною, полягає у використанні filterдля створення нової колекції без елементів, які потрібно видалити, наприклад:

let pets = animals.filter { $0 != "chimps" }

7
FYI: removeповертає вилучений елемент:let animal = animals.remove(at: 2)
2Toad

1
ми можемо фільтрувати лише на основі індексу ??
Шакір відвідав

@shaqirsaiyed Ви можете фільтрувати будь-який предикат, який ви можете придумати. наприклад, ви можете відфільтрувати всіх тварин, які закінчуються на "s".
Womble

додати тварин = домашні тварини
Puji Wahono

197

Дано

var animals = ["cats", "dogs", "chimps", "moose"]

Видаліть перший елемент

animals.removeFirst() // "cats"
print(animals)        // ["dogs", "chimps", "moose"]

Видаліть останній елемент

animals.removeLast() // "moose"
print(animals)       // ["cats", "dogs", "chimps"]

Видалити елемент в індексі

animals.remove(at: 2) // "chimps"
print(animals)           // ["cats", "dogs", "moose"]

Видаліть елемент невідомого індексу

Для лише одного елемента

if let index = animals.firstIndex(of: "chimps") {
    animals.remove(at: index)
}
print(animals) // ["cats", "dogs", "moose"]

Для декількох елементів

var animals = ["cats", "dogs", "chimps", "moose", "chimps"]

animals = animals.filter(){$0 != "chimps"}
print(animals) // ["cats", "dogs", "moose"]

Примітки

  • Вищеописані способи змінюють масив на місці (крім filter) і повертають елемент, який було видалено.
  • Швидкий посібник зі зменшення фільтра карт
  • Якщо ви не хочете змінювати вихідний масив, ви можете використовувати dropFirstабо dropLastстворити новий масив.

Оновлено до Swift 5.2


Дякуємо за ці приклади, що ви видалите елемент невідомого індексу > для кількох елементів , яке закриття ви б написали, щоб видалити, chimps && mooseнаприклад? Я шукаю щось інше, ніж{$0 != "chimps" && $0 != "moose"}

161

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

Часто ви знаєте посилання на об’єкт, який потрібно видалити в масиві. (Ви повторили свій масив і знайшли його, наприклад) У таких випадках може бути простіше працювати безпосередньо з посиланням на об'єкт, не маючи необхідності скрізь передавати його індекс. Отже, я пропоную це рішення. Він використовує оператор ідентичності !== , який ви використовуєте для перевірки, чи посилаються дві посилання на об'єкт на один і той же екземпляр об'єкта.

func delete(element: String) {
    list = list.filter() { $0 !== element }
}

Звичайно, це не працює лише для Strings.


23
Повинно бутиlist = list.filter({ $0 != element })
Крейг Груммітт

5
Ні, якщо ви хочете проконсультуватися з оператором посвідчення.
Даніель

3
array.indexOf({ $0 == obj })
jrc

2
Зверніть увагу, якщо інші об’єкти, на які посилається listце видалення, не оновлюватимуть інші посилання масиву, оскільки ви призначаєте новий масив list. Просто тонке значення, якщо видалити з масивів такий підхід.
Crashalot

1
Парадигма функціонального програмування покладається на незмінні об'єкти. Тобто, ви їх не змінюєте. Натомість ви створюєте новий об’єкт. Це те, що робить видалення, карта, зменшення тощо. список буде новоствореним об’єктом. У наведеному вище фрагменті коду я призначаю списку новоствореного об’єкта. Це працює для мене, тому що я розробляю свій код таким чином, щоб він відповідав функціональному програмуванню.
Даніель

44

Swift 5: Ось класне та просте розширення для видалення елементів у масиві без фільтрування:

   extension Array where Element: Equatable {

    // Remove first collection element that is equal to the given `object`:
    mutating func remove(object: Element) {
        guard let index = firstIndex(of: object) else {return}
        remove(at: index)
    }

}

Використання:

var myArray = ["cat", "barbecue", "pancake", "frog"]
let objectToRemove = "cat"

myArray.remove(object: objectToRemove) // ["barbecue", "pancake", "frog"]

Також працює з іншими типами, такими як, Intоскільки Element, це загальний тип:

var myArray = [4, 8, 17, 6, 2]
let objectToRemove = 17

myArray.remove(object: objectToRemove) // [4, 8, 6, 2]

1
Цікавий цей масив, де Element: Equatable part
Ніколя Манзіні

1
Блискуча. Хоча це не працює, якщо ви почнете зі списку протоколів, оскільки - тип протоколу не може відповідати "Equatable", оскільки тільки конкретні типи можуть відповідати протоколам :-(
AW101

22

Для Swift4:

list = list.filter{$0 != "your Value"}

15

Станом на Xcode 10+ та відповідно до сеансу 223 WWDC 2018, "Прийняття алгоритмів", хорошим методом буде наступнийmutating func removeAll(where predicate: (Element) throws -> Bool) rethrows

Приклад Apple:

var phrase = "The rain in Spain stays mainly in the plain."
let vowels: Set<Character> = ["a", "e", "i", "o", "u"]

phrase.removeAll(where: { vowels.contains($0) })
// phrase == "Th rn n Spn stys mnly n th pln."

див . Документація Apple

Так у прикладі ОП видалення тварин [2], "шимпанзе":

var animals = ["cats", "dogs", "chimps", "moose"]
animals.removeAll(where: { $0 == "chimps" } )
// or animals.removeAll { $0 == "chimps" }

Цей спосіб може бути кращим, оскільки він добре масштабує (лінійний проти квадратичний), читабельний і чистий. Майте на увазі, що він працює лише в Xcode 10+, а на момент написання - це в Beta.


RemoveAll (де :) зможе лише у швидкому 4.2
Влад Пулічев

14

Деякі операції стосуються масиву в Swift

Створити масив

var stringArray = ["One", "Two", "Three", "Four"]

Додати об’єкт у масив

stringArray = stringArray + ["Five"]

Отримати значення від об’єкта Index

let x = stringArray[1]

Додайте об’єкт

stringArray.append("At last position")

Вставте об’єкт в індекс

stringArray.insert("Going", atIndex: 1)

Видалити об’єкт

stringArray.removeAtIndex(3)

Значення об'єкта Concat

var string = "Concate Two object of Array \(stringArray[1]) + \(stringArray[2])"

14

Ви могли це зробити. Спочатку переконайтеся, що він Dogдійсно існує в масиві, а потім видаліть його. Додайте forзаяву, якщо ви вважаєте, що це Dogможе траплятися не один раз у вашому масиві.

var animals = ["Dog", "Cat", "Mouse", "Dog"]
let animalToRemove = "Dog"

for object in animals
{
    if object == animalToRemove{
        animals.removeAtIndex(animals.indexOf(animalToRemove)!)
    }
}

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

animals.removeAtIndex(animals.indexOf(animalToRemove)!)

Якщо у вас є обидва, рядки та числа

var array = [12, 23, "Dog", 78, 23]
let numberToRemove = 23
let animalToRemove = "Dog"

for object in array
{

    if object is Int
    {
        // this will deal with integer. You can change to Float, Bool, etc...
        if object == numberToRemove
        {
        array.removeAtIndex(array.indexOf(numberToRemove)!)
        }
    }
    if object is String
    {
        // this will deal with strings
        if object == animalToRemove
        {
        array.removeAtIndex(array.indexOf(animalToRemove)!)
        }
    }
}

Що робити, якщо мій масив не містить рядків?
Apqu

@apqu зробив ще одне оновлення '|| object == Int () 'і' || object == String () 'непотрібні
GuiSoySauce

циклічний масив набуває ефективності. перевірка .filter, .compactMap
MLBDG


10

Видаліть елементи за допомогою масиву індексів:

  1. Масив рядків та індексів

    let animals = ["cats", "dogs", "chimps", "moose", "squarrel", "cow"]
    let indexAnimals = [0, 3, 4]
    let arrayRemainingAnimals = animals
        .enumerated()
        .filter { !indexAnimals.contains($0.offset) }
        .map { $0.element }
    
    print(arrayRemainingAnimals)
    
    //result - ["dogs", "chimps", "cow"]
  2. Масив цілих чисел та індексів

    var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    let indexesToRemove = [3, 5, 8, 12]
    
    numbers = numbers
        .enumerated()
        .filter { !indexesToRemove.contains($0.offset) }
        .map { $0.element }
    
    print(numbers)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]



Видаліть елементи, використовуючи значення елемента іншого масиву

  1. Масиви цілих чисел

    let arrayResult = numbers.filter { element in
        return !indexesToRemove.contains(element)
    }
    print(arrayResult)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
  2. Масиви рядків

    let arrayLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
    let arrayRemoveLetters = ["a", "e", "g", "h"]
    let arrayRemainingLetters = arrayLetters.filter {
        !arrayRemoveLetters.contains($0)
    }
    
    print(arrayRemainingLetters)
    
    //result - ["b", "c", "d", "f", "i"]

4
Це одна відповідь на вкладиші, і це набагато ефективніше для кращого кодування та швидкого виконання.
iOSDev

Привіт @Krunal - чудова відповідь, ви можете поглянути на таке питання (звільнення зображень із масиву зображень): stackoverflow.com/questions/47735975/…
Серверний програміст

6

Стосовно альтернативи @ Suragch "Видалити елемент невідомого індексу":

Існує більш потужна версія "indexOf (element)", яка відповідатиме предикату замість самого об'єкта. Він йде за однойменною назвою, але його називають myObjects.indexOf {$ 0.property = valueToMatch}. Він повертає індекс першого відповідного елемента, знайденого в масиві myObjects.

Якщо елемент є об'єктом / структурою, можливо, ви захочете видалити цей елемент на основі значення одного з його властивостей. Наприклад, у вас є клас "Автомобіль", який має властивість car.color, і ви хочете вилучити "червоний" автомобіль зі своїх автомобілів.

if let validIndex = (carsArray.indexOf{$0.color == UIColor.redColor()}) {
  carsArray.removeAtIndex(validIndex)
}

Передбачувано ви можете переробити це, щоб вилучити "всі" червоні машини, вставивши вище, якщо заява в циклі повторення / в той час, і додавши ще один блок, щоб встановити прапор, щоб "вирватися" з циклу.


6

Швидкий 5

guard let index = orders.firstIndex(of: videoID) else { return }
orders.remove(at: index)

4

Якщо у вас є масив користувацьких об’єктів, ви можете шукати за конкретною властивістю, наприклад, ця:

    if let index = doctorsInArea.indexOf({$0.id == doctor.id}){
        doctorsInArea.removeAtIndex(index)
    }

або якщо ви хочете, наприклад, шукати по імені

    if let index = doctorsInArea.indexOf({$0.name == doctor.name}){
        doctorsInArea.removeAtIndex(index)
    }

3

Це слід зробити (не перевірено):

animals[2..3] = []

Редагувати: і вам потрібно зробити це a var, а не a let, інакше це незмінна константа.


5
При використанні (під) діапазону існуючого масиву для створення іншого масиву діапазон повинен мати 3 крапки. Сказане слід записати як тварин [2 ... 3]
zevij

3

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

extension Array where Element: Equatable {

  mutating func removeEqualItems(item: Element) {
    self = self.filter { (currentItem: Element) -> Bool in
      return currentItem != item
    }
  }

  mutating func removeFirstEqualItem(item: Element) {
    guard var currentItem = self.first else { return }
    var index = 0
    while currentItem != item {
      index += 1
      currentItem = self[index]
    }
    self.removeAtIndex(index)
  }

}

Використання:

var test1 = [1, 2, 1, 2]
test1.removeEqualItems(2) // [1, 1]

var test2 = [1, 2, 1, 2]
test2.removeFirstEqualItem(2) // [1, 1, 2]

Привіт @nburk - чудова відповідь, чи можете ви подивитись на таке питання (звільнення зображень із масиву зображень): stackoverflow.com/questions/47735975/…
Серверний програміст

1

розширення для видалення об'єкта String

extension Array {
    mutating func delete(element: String) {
        self = self.filter() { $0 as! String != element }
    }
}

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

Що таке "мутує" функція?
AwesomeElephant8232

раніше говорили, що ця функція змінить self (масив).
Варун Нахарія

1

Я використовую це розширення, майже те саме, що і Varun, але це (нижче) універсальне:

 extension Array where Element: Equatable  {
        mutating func delete(element: Iterator.Element) {
                self = self.filter{$0 != element }
        }
    }

1

Щоб видалити елементи з масиву, використовуйте remove(at:), removeLast()і removeAll().

yourArray = [1,2,3,4]

Видаліть значення на 2 позиції

yourArray.remove(at: 2)

Видаліть останнє значення з масиву

yourArray.removeLast()

Видаляє всіх членів із набору

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