extension Array {
func removeObject<T where T : Equatable>(object: T) {
var index = find(self, object)
self.removeAtIndex(index)
}
}
Ich erhalte jedoch eine Fehlermeldung var index = find(self, object)
'T' kann nicht in 'T' konvertiert werden
Ich habe es auch mit dieser Methodensignatur versucht: func removeObject(object: AnyObject)
Ich erhalte jedoch den gleichen Fehler:
'AnyObject' kann nicht in 'T' konvertiert werden.
Was ist der richtige Weg, um dies zu tun?
T where
aus Ihrer Methodendeklaration zu entfernen . Also einfachfunc removeObject<T: Equatable>
. Diese Frage ist verwandt: stackoverflow.com/questions/24091046/…Antworten:
Ab Swift 2 kann dies mit einer Protokollerweiterungsmethode erreicht werden .
removeObject()
wird als Methode für alle Typen definiert, dieRangeReplaceableCollectionType
(insbesondereArray
) entsprechen, wenn die Elemente der SammlungEquatable
:Beispiel:
Update für Swift 2 / Xcode 7 Beta 2: Wie Airspeed Velocity in den Kommentaren feststellte, ist es jetzt tatsächlich möglich, eine Methode für einen generischen Typ zu schreiben, der die Vorlage restriktiver macht, sodass die Methode nun tatsächlich als Erweiterung definiert werden kann von
Array
:Die Protokollerweiterung hat immer noch den Vorteil, dass sie auf einen größeren Satz von Typen anwendbar ist.
Update für Swift 3:
quelle
remove(object: Element)
, um den Swift API-Designrichtlinien zu entsprechen und Ausführlichkeit zu vermeiden. Ich habe eine Bearbeitung eingereicht, die dies widerspiegelt.Sie können keine Methode für einen generischen Typ schreiben, der die Vorlage restriktiver macht.
HINWEIS : Ab Swift 2.0 können Sie jetzt Methoden schreiben, die die Vorlage einschränken. Wenn Sie Ihren Code auf 2.0 aktualisiert haben, finden Sie in anderen Antworten weiter unten neue Optionen, um dies mithilfe von Erweiterungen zu implementieren.
Der Grund, warum Sie den Fehler erhalten,
'T' is not convertible to 'T'
ist, dass Sie tatsächlich ein neues T in Ihrer Methode definieren, das überhaupt nicht mit dem ursprünglichen T zusammenhängt. Wenn Sie T in Ihrer Methode verwenden möchten, können Sie dies tun, ohne es in Ihrer Methode anzugeben.Der Grund, warum Sie den zweiten Fehler erhalten,
'AnyObject' is not convertible to 'T'
ist, dass nicht alle möglichen Werte für T alle Klassen sind. Damit eine Instanz in AnyObject konvertiert werden kann, muss es sich um eine Klasse handeln (es kann sich nicht um eine Struktur, eine Aufzählung usw. handeln).Am besten machen Sie es zu einer Funktion, die das Array als Argument akzeptiert:
Anstatt das ursprüngliche Array zu ändern, können Sie Ihre Methode threadsicherer und wiederverwendbarer machen, indem Sie eine Kopie zurückgeben:
Als Alternative, die ich nicht empfehle, kann Ihre Methode stillschweigend fehlschlagen, wenn der im Array gespeicherte Typ nicht in die Methodenvorlage konvertiert werden kann (das ist gleichwertig). (Aus Gründen der Übersichtlichkeit verwende ich U anstelle von T für die Vorlage der Methode):
Bearbeiten Um den stillen Fehler zu überwinden, können Sie den Erfolg als Bool zurückgeben:
quelle
find
Methode nicht verwenden ?Equatable
Protokoll implementiert . UIView tut dies ja, es wird mit UIViews funktionierenenumerate(self)
muss reparieren zuself.enumerate()
kurz und prägnant:
quelle
inout
werden. Selbst mit deminout
intakten könnte man verwenden,array = array.filter() { $0 != object }
denke ich.Nachdem ich all das gelesen habe, ist die beste Antwort für mich:
Stichprobe:
Swift 2 (xcode 7b4) Array-Erweiterung:
Stichprobe:
Swift 3.1 Update
Kam jetzt darauf zurück, da Swift 3.1 heraus ist. Im Folgenden finden Sie eine Erweiterung, die umfassende, schnelle, mutierende und erstellende Varianten bietet.
Proben:
quelle
filter
Funktion diese Funktionalität bereits für Sie übernimmt. Dies scheint die Funktionalität zu duplizieren. Aber trotzdem eine gute Antwort:]Mit Protokollerweiterungen können Sie dies tun,
Gleiche Funktionalität für Klassen,
Swift 2
Swift 3
Wenn eine Klasse Equatable implementiert, wird sie mehrdeutig und der Compiler gibt einen Fehler aus.
quelle
Binary operator '===' cannot be applied to two elements of type '_' and 'Element'
Mit Protokollerweiterungen in Swift 2.0
quelle
Was ist mit Filterung? Das Folgende funktioniert auch mit [AnyObject] recht gut.
quelle
Es gibt eine andere Möglichkeit, ein Element aus einem Array zu entfernen, ohne dass eine unsichere Verwendung möglich ist, da der generische Typ des zu entfernenden Objekts nicht mit dem Typ des Arrays identisch sein kann. Die Verwendung von Optionen ist auch nicht der perfekte Weg, da sie sehr langsam sind. Sie können daher einen Verschluss verwenden, wie er beispielsweise bereits beim Sortieren eines Arrays verwendet wird.
Wenn Sie die
Array
Klasse mit dieser Funktion erweitern, können Sie Elemente wie folgt entfernen:Sie können ein Element jedoch nur dann entfernen, wenn es dieselbe Speicheradresse hat (
AnyObject
natürlich nur für protokollkonforme Klassen ):Das Gute ist, dass Sie den zu vergleichenden Parameter angeben können. Wenn Sie beispielsweise ein Array von Arrays haben, können Sie den Gleichheitsabschluss als angeben,
{ $0.count == $1.count }
und das erste Array mit der gleichen Größe wie das zu entfernende Array wird aus dem Array entfernt.Sie können den Funktionsaufruf sogar verkürzen, indem Sie die Funktion als haben
mutating func removeFirst(equality: (Element) -> Bool) -> Bool
, dann die if-Auswertung durch ersetzenequality(item)
und die Funktion beispielsweise durch aufrufenarray.removeFirst({ $0 == "Banana" })
.quelle
==
es sich um eine Funktion handelt, können Sie sie auch für jeden implementierten Typ==
(wie String, Int usw.) so aufrufen :array.removeFirst("Banana", equality:==)
Keine Notwendigkeit zu verlängern:
quelle
Verwenden
indexOf
anstelle einesfor
oderenumerate
:quelle
Vielleicht habe ich die Frage nicht verstanden.
Warum sollte das nicht funktionieren?
quelle
Am Ende hatte ich folgenden Code.
quelle
Ich habe es geschafft, a
[String:AnyObject]
aus einem Array zu entfernen,[[String:AnyObject]]
indem ich eine Anzahl außerhalb einer for-Schleife implementiert habe, um den Index darzustellen, da.find
und.filter
nicht kompatibel mit[String:AnyObject]
.quelle
Implementierung in Swift 2:
quelle
Ich konnte es zum Laufen bringen mit:
quelle
if(index)
ist ungültig