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'
Kamlesh Shingarakhiya
quelle
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"}
vadian
quelle
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" }
Nyxee
quelle
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)
}
Mark Semsel
quelle
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) 
Luca Davanzo
quelle
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")
Mohsenasm
quelle
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)
    }
Tj3n
quelle
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)
}
Sergey Di.
quelle
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)
}
Jörg
quelle
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

Dili
quelle
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

yoAlex5
quelle
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
    }
}
Renetik
quelle
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

Mahesh Cheliya
quelle
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.).

Andrew Kingdom
quelle