Jak usunąć element z tablicy w Swift

236

Jak mogę rozbroić / usunąć element z tablicy w nowym języku Apple Swift?

Oto kod:

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

Jak można animals[2]usunąć element z tablicy?

Leopold Joy
źródło

Odpowiedzi:

300

Słowo letkluczowe służy do deklarowania stałych, których nie można zmienić. Jeśli chcesz zmodyfikować zmienną, powinieneś użyć varzamiast niej, np .:

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

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

Nie mutującą alternatywą, która zachowa oryginalną kolekcję bez zmian, jest filterutworzenie nowej kolekcji bez elementów, które chcesz usunąć, np .:

let pets = animals.filter { $0 != "chimps" }
mit
źródło
7
FYI: removezwraca usunięty element:let animal = animals.remove(at: 2)
2Toad
1
czy możemy filtrować tylko na podstawie indeksu?
shaqir saiyed
@shaqirsaiyed Możesz filtrować według dowolnego predykatu, który wymyślisz. np. możesz odfiltrować wszystkie zwierzęta, które kończą się na „s”.
Womble
dodaj zwierzęta = zwierzęta domowe
Puji Wahono
197

Dany

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

Usuń pierwszy element

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

Usuń ostatni element

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

Usuń element z indeksu

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

Usuń element o nieznanym indeksie

Tylko dla jednego elementu

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

Dla wielu elementów

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

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

Notatki

  • Powyższe metody modyfikują tablicę w miejscu (z wyjątkiem filter) i zwracają usunięty element.
  • Szybki przewodnik po filtrze mapy Zmniejsz
  • Jeśli nie chcesz modyfikować oryginalnej tablicy, możesz użyć dropFirstlub dropLastutworzyć nową tablicę.

Zaktualizowano do Swift 5.2

Suragch
źródło
Dzięki za te przykłady, w tobie Usuń element o nieznanym indeksie > dla wielu elementów , jakie zamknięcie napisałbyś chimps && moosena przykład, aby usunąć ? Szukam czegoś innego niż{$0 != "chimps" && $0 != "moose"}
161

Powyższe odpowiedzi wydają się zakładać, że znasz indeks elementu, który chcesz usunąć.

Często znasz odniesienie do obiektu, który chcesz usunąć z tablicy. (Iterowałeś przez tablicę i ją znalazłeś, np.) W takich przypadkach może być łatwiej pracować bezpośrednio z odwołaniem do obiektu bez konieczności przekazywania wszędzie jego indeksu. Dlatego proponuję to rozwiązanie. Używa operatora tożsamości !== , którego używasz do testowania, czy oba odwołania do obiektów odnoszą się do tej samej instancji obiektu.

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

Oczywiście to nie działa tylko dla Strings.

Daniel
źródło
23
Powinny byćlist = list.filter({ $0 != element })
Craig Grummitt
5
Nie, jeśli chcesz skontaktować się z operatorem tożsamości.
Daniel
3
array.indexOf({ $0 == obj })
jrc
2
Uwaga: jeśli inne obiekty odwołują się do listtego usunięcia, nie zaktualizuje innych odwołań do tablicy, ponieważ przypisujesz nową tablicę list. Tylko subtelna implikacja, jeśli usuniesz z tablic za pomocą tego podejścia.
Crashalot
1
Paradygmat programowania funkcjonalnego opiera się na niezmiennych obiektach. Tzn. Nie zmieniasz ich. Zamiast tego tworzysz nowy obiekt. To właśnie robi usuwanie, mapowanie, zmniejszanie itp. lista będzie nowo utworzonym obiektem. W powyższym fragmencie kodu przypisuję powrót do listy nowo utworzonego obiektu. To działa dla mnie, ponieważ projektuję kod w sposób zgodny z programowaniem funkcjonalnym.
Daniel
44

Swift 5: Oto fajne i łatwe rozszerzenie do usuwania elementów z tablicy bez filtrowania:

   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)
    }

}

Stosowanie :

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

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

Działa również z innymi typami, np. IntPonieważ Elementjest to typ ogólny:

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

myArray.remove(object: objectToRemove) // [4, 8, 6, 2]
Skaal
źródło
1
Ciekawa tablica, w której element: Część do wyrównania
Nicolas Manzini,
1
Znakomity. Chociaż to nie działa, jeśli zaczynasz od listy protokołów, ponieważ - Typ protokołu nie może być zgodny z „Equatable”, ponieważ tylko konkretne typy mogą być zgodne z protokołami :-(
AW101,
22

W przypadku Swift4:

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

źródło
15

Począwszy od Xcode 10+ i zgodnie z sesją WWDC 2018 223 „Algorytmy obejmujące” dobrą metodą będziemutating func removeAll(where predicate: (Element) throws -> Bool) rethrows

Przykład 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."

widzieć dokumentacja Apple

Tak więc w przykładzie PO usunięcie zwierząt [2], „szympansów”:

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

Ta metoda może być preferowana, ponieważ dobrze się skaluje (liniowa vs kwadratowa), jest czytelna i czysta. Pamiętaj, że działa tylko w Xcode 10+, a od momentu pisania jest w wersji beta.

davidrynn
źródło
removeAll (gdzie :) będzie w stanie tylko w szybkim 4.2
Vlad Pulichev
14

Kilka operacji dotyczy tablicy w trybie Swift

Utwórz tablicę

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

Dodaj obiekt w szyku

stringArray = stringArray + ["Five"]

Uzyskaj wartość z obiektu indeksu

let x = stringArray[1]

Dołącz obiekt

stringArray.append("At last position")

Wstaw obiekt o indeksie

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

Usuń obiekt

stringArray.removeAtIndex(3)

Concat Wartość obiektu

var string = "Concate Two object of Array \(stringArray[1]) + \(stringArray[2])"
Solid Soft
źródło
14

Mógłbyś to zrobić. Najpierw upewnij się, że Dognaprawdę istnieje w tablicy, a następnie usuń ją. Dodaj forinstrukcję, jeśli uważasz, że Dogmoże się zdarzyć więcej niż jeden raz na tablicy.

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

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

Jeśli jesteś pewien, że Dogwychodzi z tablicy i zdarzyło się to tylko raz, zrób to:

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

Jeśli masz zarówno ciągi, jak i liczby

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
źródło
Co jeśli moja tablica nie zawiera ciągów?
Apqu
@apqu zrobił kolejną aktualizację ”|| object == Int () ”i„ || object == String () 'są niepotrzebne
GuiSoySauce,
zapętlanie tablicy powoduje jeszcze większą wydajność. sprawdź .filter, .compactMap
MLBDG
10

Usuń elementy za pomocą tablicy indeksów:

  1. Tablica ciągów i indeksów

    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. Tablica liczb całkowitych i indeksów

    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]



Usuń elementy, używając wartości elementu innej tablicy

  1. Tablice liczb całkowitych

    let arrayResult = numbers.filter { element in
        return !indexesToRemove.contains(element)
    }
    print(arrayResult)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
  2. Tablice ciągów

    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
źródło
4
Jest to jedna odpowiedź liniowa i jest bardzo wydajna dla lepszego kodowania i szybkiego wykonania.
iOSDev
Cześć @Krunal - świetna odpowiedź, czy mógłbyś rzucić okiem na następujące pytanie (zwalnianie obrazów z tablicy obrazów): stackoverflow.com/questions/47735975/…
programista serwera
6

Odnośnie alternatywy @ Suragch do „Usuń element o nieznanym indeksie”:

Istnieje mocniejsza wersja „indexOf (element)”, która będzie pasować do predykatu zamiast samego obiektu. Ma taką samą nazwę, ale jest wywoływana przez myObjects.indexOf {$ 0.property = valueToMatch}. Zwraca indeks pierwszego pasującego elementu znalezionego w tablicy myObjects.

Jeśli element jest obiektem / strukturą, możesz chcieć usunąć ten element na podstawie wartości jednej z jego właściwości. Na przykład masz klasę samochodów posiadającą właściwość car.color i chcesz usunąć „czerwony” samochód z tablicy carsArray.

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

Można było przewidzieć, że można to przerobić, aby usunąć „wszystkie” czerwone samochody, osadzając powyższą instrukcję if w pętli powtarzania / while i dołączając blok else, aby ustawić flagę „wyłamującą się” z pętli.

ObjectiveTC
źródło
6

Szybki 5

guard let index = orders.firstIndex(of: videoID) else { return }
orders.remove(at: index)
Jerome
źródło
4

Jeśli masz szereg obiektów niestandardowych, możesz wyszukiwać według określonych właściwości, takich jak:

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

lub jeśli chcesz na przykład wyszukać według nazwy

    if let index = doctorsInArea.indexOf({$0.name == doctor.name}){
        doctorsInArea.removeAtIndex(index)
    }
Abo3atef
źródło
3

Powinno to zrobić (nie przetestowane):

animals[2..3] = []

Edycja: i musisz zrobić to, a varnie let, w przeciwnym razie jest to niezmienna stała.

Plik analogowy
źródło
5
W przypadku użycia (pod) zakresu istniejącej tablicy do utworzenia innej tablicy, zakres musi zawierać 3 kropki. Powyższe należy zapisać jako zwierzęta [2 ... 3]
zevij
3

Wymyśliłem następujące rozszerzenie, które zajmuje się usuwaniem elementów z Array, zakładając elementy w Arraynarzędziu 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)
  }

}

Stosowanie:

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

var test2 = [1, 2, 1, 2]
test2.removeFirstEqualItem(2) // [1, 1, 2]
nburk
źródło
Cześć @nburk - świetna odpowiedź, czy mógłbyś rzucić okiem na następujące pytanie (uwalnianie obrazów z tablicy obrazów): stackoverflow.com/questions/47735975/...
programista serwera
1

rozszerzenie do usunięcia obiektu String

extension Array {
    mutating func delete(element: String) {
        self = self.filter() { $0 as! String != element }
    }
}
Varun Naharia
źródło
wymuszenie rozpakowywania może spowodować awarię, myślę, że powinieneś tego uniknąć w tym przypadku.
user3206558,
Co to jest „mutujący” func?
AwesomeElephant8232
zwykł mówić, że ta funkcja zmieni ja (tablicę).
Varun Naharia
1

Używam tego rozszerzenia, prawie takiego samego jak Varun, ale to (poniżej) jest uniwersalne:

 extension Array where Element: Equatable  {
        mutating func delete(element: Iterator.Element) {
                self = self.filter{$0 != element }
        }
    }
użytkownik3206558
źródło
1

Aby usunąć elementy z tablicy, użyj remove(at:), removeLast()i removeAll().

yourArray = [1,2,3,4]

Usuń wartość z pozycji 2

yourArray.remove(at: 2)

Usuń ostatnią wartość z tablicy

yourArray.removeLast()

Usuwa wszystkich członków z zestawu

yourArray.removeAll()
PatelFab
źródło