Как удалить элемент из массива в Swift

236

Как можно удалить / удалить элемент из массива на новом языке Apple Swift?

Вот некоторый код:

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" }
mythz
источник
7
К вашему сведению: removeвозвращает удаленный элемент:let animal = animals.remove(at: 2)
2Toad
1
мы можем фильтровать только на основе индекса?
Шакир сказал
@shaqirsaiyed Вы можете фильтровать любые предикаты, которые можете придумать. Например, вы можете отфильтровать всех животных, которые заканчиваются на "s".
Уомбл
добавить животных = домашних животных
Пуджи Вахоно
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) и возвращают удаленный элемент.
  • Swift Guide to Map Filter Reduce
  • Если вы не хотите изменять исходный массив, вы можете использовать dropFirstили dropLastдля создания нового массива.

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

Suragch
источник
Спасибо за эти примеры, вы удалите элемент с неизвестным индексом > для нескольких элементов , какое замыкание вы бы написали для удаления, chimps && mooseнапример? Я ищу что-то другое, чем{$0 != "chimps" && $0 != "moose"}
161

Представленные выше ответы предполагают, что вы знаете индекс элемента, который хотите удалить.

Часто вы знаете ссылку на объект, который хотите удалить в массиве. (Вы перебрали свой массив и нашли его, например). В таких случаях может быть проще работать напрямую со ссылкой на объект, не пропуская при этом всюду его индекс. Следовательно, я предлагаю это решение. Он использует оператор идентификации !== , который вы используете, чтобы проверить, ссылаются ли обе ссылки на один и тот же экземпляр объекта.

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

Конечно, это не просто работает для Stringс.

Даниил
источник
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
Brilliant. Хотя это не сработает, если вы начнете со списка протоколов, так как - тип протокола не может соответствовать 'Equatable', поскольку только конкретные типы могут соответствовать протоколам :-(
AW101
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+, и на момент написания статьи это в бета-версии.

davidrynn
источник
удалить все (где :) сможет только в swift 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 Object value

var string = "Concate Two object of Array \(stringArray[1]) + \(stringArray[2])"
Solid Soft
источник
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)!)
        }
    }
}
GuiSoySauce
источник
Что если мой массив не содержит строк?
Апк
@apqu сделал еще одно обновление '|| object == Int () 'и' || object == String () 'не нужны
GuiSoySauce
зацикливание массива идет опять-таки на эффективность. проверить .filter, .compactMap
MLBDG
10

Удалить элементы с помощью массива indexes:

  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"]
Krunal
источник
4
Это один линейный ответ, и он намного эффективнее для лучшего кодирования и быстрого выполнения.
iOSDev
Привет @Krunal - отличный ответ, не могли бы вы взглянуть на следующий вопрос (освобождение изображений из массива изображений): stackoverflow.com/questions/47735975/…
Программист сервера
6

Относительно альтернативы @ Suragch "Удалить элемент неизвестного индекса":

Существует более мощная версия indexOf (element), которая будет соответствовать предикату, а не самому объекту. Он имеет то же имя, но называется myObjects.indexOf {$ 0.property = valueToMatch}. Возвращает индекс первого соответствующего элемента, найденного в массиве myObjects.

Если элемент является объектом / структурой, вы можете удалить этот элемент на основе значения одного из его свойств. Например, у вас есть класс Car с свойством car.color, и вы хотите удалить «красный» автомобиль из вашего carsArray.

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

Как и ожидалось, вы могли бы переработать это, чтобы удалить «все» красные машины, добавив вышеприведенный оператор if в цикл repeat / while и прикрепив блок else, чтобы установить флаг для «выхода» из цикла.

ObjectiveTC
источник
6

Swift 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)
    }
Abo3atef
источник
3

Это должно сделать это (не проверено):

animals[2..3] = []

Изменить: и вам нужно сделать это, а varне let, иначе это неизменяемая константа.

Аналоговый файл
источник
5
При использовании (под) диапазона существующего массива для создания другого массива диапазон должен иметь 3 точки.
Вышесказанное
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
источник
Привет @nburk - отличный ответ, не могли бы вы взглянуть на следующий вопрос (освобождение изображений из массива изображений): stackoverflow.com/questions/47735975/…
Программист сервера
1

расширение для удаления объекта String

extension Array {
    mutating func delete(element: String) {
        self = self.filter() { $0 as! String != element }
    }
}
Варун Нагария
источник
принудительное развертывание может привести к сбою, я думаю, вам следует избегать его в этом случае.
user3206558
Что такое "мутирующий" функционал?
AwesomeElephant8232
раньше он говорил, что эта функция изменит себя (массив).
Варун Нагария
1

Я использую это расширение, почти такое же, как у Варуна, но это (ниже) универсально:

 extension Array where Element: Equatable  {
        mutating func delete(element: Iterator.Element) {
                self = self.filter{$0 != element }
        }
    }
user3206558
источник
1

Чтобы удалить элементы из массива, используйте remove(at:), removeLast()и removeAll().

yourArray = [1,2,3,4]

Удалить значение в 2 позиции

yourArray.remove(at: 2)

Удалить последнее значение из массива

yourArray.removeLast()

Удаляет всех участников из набора

yourArray.removeAll()
PatelFab
источник