Objekt aus dem Array in Swift 3 entfernen


89

In meiner Anwendung habe ich beim Auswählen einer Zelle ein Objekt im Array hinzugefügt und beim erneuten Auswählen der Zelle die Auswahl aufgehoben und das Objekt entfernt. Ich habe diesen Code verwendet, aber mir einen Fehler gegeben.

extension Array {
    func indexOfObject(object : AnyObject) -> NSInteger {
        return (self as NSArray).indexOfObject(object)
    }

    mutating func removeObject(object : AnyObject) {
        for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) {
            self.removeAtIndex(index)
        }
    }
}

class MyViewController: UITableViewController {
    var arrContacts: [Any] = []
    var contacts: [Any] = []

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        arrContacts.removeObject(contacts[indexPath.row])
    }
}

Es gibt mir 2 Fehler wie folgt:

C-style for statement has been removed in Swift 3
Value of type '[Any]' has no member 'removeObject'

Sie können Set<Contact>ein Array anstelle eines Arrays verwenden. Können Sie weitere Informationen zu Ihrem Kontaktobjekt bereitstellen? Wenn Sie es selbst gemacht haben, müssen Sie es anpassen Hashableund Equatablein ein Set setzen
Paulw11

Antworten:


160

Das Swift-Äquivalent zu NSMutableArray's removeObjectist:

var array = ["alpha", "beta", "gamma"]

if let index = array.firstIndex(of: "beta") {
    array.remove(at: index)
}

wenn die Objekte eindeutig sind . Es besteht überhaupt keine Notwendigkeit zum Gießen NSArrayund VerwendenindexOfObject:

Die API index(of:funktioniert auch, dies führt jedoch zu einer unnötigen impliziten Umwandlung in NSArray.

Wenn es mehrere Vorkommen desselben Objekts gibt, verwenden Sie filter. In Fällen wie Datenquellen-Arrays, in denen ein Index einem bestimmten Objekt zugeordnet firstIndex(ofist, ist dies jedoch vorzuziehen, da er schneller als ist filter.

Aktualisieren:

In Swift 4.2 und höher können Sie ein oder mehrere Vorkommen entfernen betamit removeAll(where:):

array.removeAll{$0 == "beta"}

32
Dies ist die beste Antwort, aber es ist mehr als dumm, keine Entfernung zu haben (Objekt: "Beta").
Zeeple

5
Ich denke, .index(of: ist nur verfügbar, wenn die Sammlung EquatableTypen enthält .
Adam Waite

@AdamWaite Ja, aber dies gilt auch für die Foundation-Typen.
Vadian

Das ist nicht richtig, was ist, wenn Sie mehr als eine "Beta" haben? Dies funktioniert nur, wenn das Array nicht mehr als ein Vorkommen enthält. Die richtige Antwort ist die Verwendung eines Filters oder das Ausführen dieser Antwort in einer Weilewhile let index = array.index(of: "beta") { array.remove(at: index) }
juancazalla

@juancazalla Sie haben Recht, aber wenn das Array mehr als ein Vorkommen enthalten kann, verwenden Sie die filterLösung. Aber wenn die Objekte einzigartig sind, verwenden Sie sie immer, index(ofweil sie viel performanter sind alsfilter
vadian

71
var a = ["one", "two", "three", "four", "five"]

// Remove/filter item with value 'three'
a = a.filter { $0 != "three" }

7
Das ist die richtige Swift-Lösung, die die von der Sprache angebotenen Syntax-Goodies verwendet.
Michael

1
Was ist, wenn Gegenstand ein Objekt ist?
TomSawyer

@ TomSawyer, um ein Objekt herauszufiltern, verwenden Sie $ 0! ==
Mike Taverne

25

Für Swift 3 können Sie index (where :) verwenden und einen Abschluss einfügen, der den Vergleich eines Objekts im Array ($ 0) mit dem gewünschten Objekt durchführt.

var array = ["alpha", "beta", "gamma"]
if let index = array.index(where: {$0 == "beta"}) {
  array.remove(at: index)
}

Funktioniert dies, wenn ich mehrere Objekte entfernen möchte? wie (wo: {$ 0 == "beta" || $ 0 == "gamma"})
Irshad Mohamed

16

Eine andere nette und nützliche Lösung besteht darin, diese Art von Erweiterung zu erstellen:

extension Array where Element: Equatable {

    @discardableResult mutating func remove(object: Element) -> Bool {
        if let index = index(of: object) {
            self.remove(at: index)
            return true
        }
        return false
    }

    @discardableResult mutating func remove(where predicate: (Array.Iterator.Element) -> Bool) -> Bool {
        if let index = self.index(where: { (element) -> Bool in
            return predicate(element)
        }) {
            self.remove(at: index)
            return true
        }
        return false
    }

}

Auf diese Weise, wenn Sie Ihr Array mit benutzerdefinierten Objekten haben:

let obj1 = MyObject(id: 1)
let obj2 = MyObject(id: 2)
var array: [MyObject] = [obj1, obj2]

array.remove(where: { (obj) -> Bool in
    return obj.id == 1
})
// OR
array.remove(object: obj2) 

1
Dies funktioniert nur, wenn das Array nicht mehr als ein Vorkommen enthält. Die richtige Antwort ist die Verwendung eines Filters oder das Ausführen dieser Antwort in einer Weile. Als Benutzer dieser Erweiterung erwarte ich, dass alle Vorkommen und nicht nur eines entfernt werden
juancazalla

Es ist schön, aber es sollte sein, remove(element: Element)dass Sie in Array auch Typen wie Int, Double speichern können - sie sind keine Objekte.
Radek Wilczak

8

Verwenden Sie in Swift 5 Folgendes Extension:

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.firstIndex(of: element) {
            self.remove(at: i)
        }
    }
}

Beispiel:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

Verwenden Sie in Swift 3 Folgendes Extension:

extension Array where Element: Equatable{
    mutating func remove (element: Element) {
        if let i = self.index(of: element) {
            self.remove(at: i)
        }
    }
}

Beispiel:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

6
  1. for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) ist für Schleife im C-Stil und wurde entfernt

  2. Ändern Sie Ihren Code in etwa so, um alle ähnlichen Objekte zu entfernen, wenn sie eine Schleife durchlaufen haben:

    let indexes = arrContacts.enumerated().filter { $0.element == contacts[indexPath.row] }.map{ $0.offset }
    for index in indexes.reversed() {
       arrContacts.remove(at: index)
    }

Aufzählung -> Filter -> Zuordnen und Entfernen (at) ist eine intelligente Lösung. Empfehlen Sie dieses
Ryan X

4

Swift 4

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]

if let index = students.firstIndex(where: { $0.hasPrefix("A") }) {
   students.remove(at: index)
}

3

Die richtige und funktionierende einzeilige Lösung zum Löschen eines eindeutigen Objekts (mit dem Namen "objectToRemove") aus einem Array dieser Objekte (mit dem Namen "array") in Swift 3 lautet:

if let index = array.enumerated().filter( { $0.element === objectToRemove }).map({ $0.offset }).first {
   array.remove(at: index)
}

1

Versuchen Sie dies in Swift 3

array.remove(at: Index)

Anstatt

array.removeAtIndex(index)

Aktualisieren

"Declaration is only valid at file scope".

Stellen Sie sicher, dass sich das Objekt im Gültigkeitsbereich befindet. Sie können den Bereich "intern" angeben, was standardmäßig der Fall ist.

index(of:<Object>) um zu arbeiten, sollte die Klasse konform sein Equatable


1

In Swift 3 und 4

var array = ["a", "b", "c", "d", "e", "f"]

for (index, element) in array.enumerated().reversed() {
    array.remove(at: index)
}

Ab Swift 4.2 können Sie einen fortgeschritteneren Ansatz verwenden (schneller und speichereffizienter).

array.removeAll(where: { $0 == "c" })

anstatt

array = array.filter { !$0.hasPrefix("c") }

Lesen Sie hier mehr


1

Erweiterung für Array, um dies einfach zu machen und Verkettung für Swift 4.2 und höher zu ermöglichen:

public extension Array where Element: Equatable {
    @discardableResult
    public mutating func remove(_ item: Element) -> Array {
        if let index = firstIndex(where: { item == $0 }) {
            remove(at: index)
        }
        return self
    }

    @discardableResult
    public mutating func removeAll(_ item: Element) -> Array {
        removeAll(where: { item == $0 })
        return self
    }
}

Argumentbezeichnungen '(wo :)' stimmen nicht mit verfügbaren Überladungen
überein

1
@ jeet.chanchawat gut wahrscheinlich andere schnelle Version dann ... Oh, diese Frage war für 3? Nun, ich glaube ich hatte 4.2 zum Zeitpunkt des Schreibens, aber ich erinnere mich jetzt nicht, werde es später überprüfen, es hat definitiv für mich
funktioniert

0

Dies ist die offizielle Antwort, um den Index eines bestimmten Objekts zu finden. Anschließend können Sie jedes Objekt mithilfe dieses Index leicht entfernen:

var students = ["Ben", "Ivy", "Jordell", "Maxime"]
if let i = students.firstIndex(of: "Maxime") {
     // students[i] = "Max"
     students.remove(at: i)
}
print(students)
// Prints ["Ben", "Ivy", "Jordell"]

Hier ist der Link: https://developer.apple.com/documentation/swift/array/2994720-firstindex


0

Das habe ich benutzt (Swift 5) ...

    extension Array where Element:Equatable
    {
        @discardableResult
        mutating func removeFirst(_ item:Any ) -> Any? {
            for index in 0..<self.count {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
            }
            return nil
        }
        @discardableResult
        mutating func removeLast(_ item:Any ) -> Any? {
            var index = self.count-1
            while index >= 0 {
                if(item as? Element == self[index]) {
                    return self.remove(at: index)
                }
                index -= 1
            }
            return nil
        }
    }

    var arrContacts:[String] = ["A","B","D","C","B","D"]
    var contacts: [Any] = ["B","D"]
    print(arrContacts)
    var index = 1
    arrContacts.removeFirst(contacts[index])
    print(arrContacts)
    index = 0
    arrContacts.removeLast(contacts[index])
    print(arrContacts)

Ergebnisse:

   ["A", "B", "D", "C", "B", "D"]
   ["A", "B", "C", "B", "D"]
   ["A", "B", "C", "D"]

Wichtig: Das Array, aus dem Sie Elemente entfernen, muss gleichwertige Elemente enthalten (z. B. Objekte, Zeichenfolgen, Zahlen usw.).

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.