Extensión de matriz para eliminar el object por valor

extension Array { func removeObject<T where T : Equatable>(object: T) { var index = find(self, object) self.removeAtIndex(index) } } 

Sin embargo, aparece un error en var index = find(self, object)

'T' no es convertible a 'T'

También probé con este método signature: func removeObject(object: AnyObject) , sin embargo, recibo el mismo error:

'AnyObject' no es convertible a 'T'

¿Cuál es la forma apropiada de hacer esto?

A partir de Swift 2 , esto se puede lograr con un método de extensión de protocolo . removeObject() se define como un método en todos los types que se ajusta a RangeReplaceableCollectionType (en particular en Array ) si los elementos de la colección son Equatable :

 extension RangeReplaceableCollectionType where Generator.Element : Equatable { // Remove first collection element that is equal to the given `object`: mutating func removeObject(object : Generator.Element) { if let index = self.indexOf(object) { self.removeAtIndex(index) } } } 

Ejemplo:

 var ar = [1, 2, 3, 2] ar.removeObject(2) print(ar) // [1, 3, 2] 

Actualización para Swift 2 / Xcode 7 beta 2: Como la velocidad de velocidad aérea se notó en los comentarios, ahora es posible escribir un método en un tipo genérico que sea más restrictivo en la plantilla, por lo que el método ahora podría definirse como una extensión de Array :

 extension Array where Element : Equatable { // ... same method as above ... } 

La extensión del protocolo todavía tiene la ventaja de ser aplicable a un set más grande de types.

Actualización para Swift 3:

 extension Array where Element: Equatable { // Remove first collection element that is equal to the given `object`: mutating func remove(object: Element) { if let index = index(of: object) { remove(at: index) } } } 

No puede escribir un método en un tipo genérico que sea más restrictivo en la plantilla.

NOTA : a partir de Swift 2.0, ahora puede escribir methods que son más restrictivos en la plantilla. Si ha actualizado su código a 2.0, vea otras respuestas más abajo para get nuevas opciones para implementar esto usando extensiones.

La razón por la que obtienes el error 'T' is not convertible to 'T' es que estás definiendo una nueva T en tu método que no está relacionada en absoluto con la T. original. Si quisieras usar T en tu método, puede hacerlo sin especificarlo en su método.

La razón por la que obtiene el segundo error 'AnyObject' is not convertible to 'T' es que todos los valores posibles para T no son todas classs. Para que una instancia se convierta a AnyObject, debe ser una class (no puede ser una estructura, enumeración, etc.).

Su mejor opción es convertirlo en una function que acepte la matriz como argumento:

 func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) { } 

O en lugar de modificar la matriz original, puede hacer que su método sea más seguro y reutilizable al devolver una copy:

 func arrayRemovingObject<T : Equatable>(object: T, fromArray array: [T]) -> [T] { } 

Como una alternativa que no recomiendo, puede hacer que su método falle silenciosamente si el tipo almacenado en la matriz no se puede convertir a la plantilla de methods (que es equitativo). (Para mayor claridad, estoy usando U en lugar de T para la plantilla del método):

 extension Array { mutating func removeObject<U: Equatable>(object: U) { var index: Int? for (idx, objectToCompare) in enumerate(self) { if let to = objectToCompare as? U { if object == to { index = idx } } } if(index != nil) { self.removeAtIndex(index!) } } } var list = [1,2,3] list.removeObject(2) // Successfully removes 2 because types matched list.removeObject("3") // fails silently to remove anything because the types don't match list // [1, 3] 

Editar Para superar la falla silenciosa, puede devolver el éxito como un bool:

 extension Array { mutating func removeObject<U: Equatable>(object: U) -> Bool { for (idx, objectToCompare) in self.enumerate() { //in old swift use enumerate(self) if let to = objectToCompare as? U { if object == to { self.removeAtIndex(idx) return true } } } return false } } var list = [1,2,3,2] list.removeObject(2) list list.removeObject(2) list 

breve y concisa:

 func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) { var index = find(array, object) array.removeAtIndex(index!) } 

Después de leer todo lo anterior, para mí la mejor respuesta es:

 func arrayRemovingObject<U: Equatable>(object: U, # fromArray:[U]) -> [U] { return fromArray.filter { return $0 != object } } 

Muestra:

 var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"] myArray = arrayRemovingObject("Cat", fromArray:myArray ) 

Swift 2 (xcode 7b4) extensión de la matriz:

 extension Array where Element: Equatable { func arrayRemovingObject(object: Element) -> [Element] { return filter { $0 != object } } } 

Muestra:

 var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"] myArray = myArray.arrayRemovingObject("Cat" ) 

Actualización Swift 3.1

Regresé a esto ahora que Swift 3.1 está fuera. A continuación se muestra una extensión que proporciona variantes exhaustivas, rápidas, mutantes y creadoras.

 extension Array where Element:Equatable { public mutating func remove(_ item:Element ) { var index = 0 while index < self.count { if self[index] == item { self.remove(at: index) } else { index += 1 } } } public func array( removing item:Element ) -> [Element] { var result = self result.remove( item ) return result } } 

Muestras:

 // Mutation... var array1 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"] array1.remove("Cat") print(array1) // ["Dog", "Turtle", "Socks"] // Creation... let array2 = ["Cat", "Dog", "Turtle", "Cat", "Fish", "Cat"] let array3 = array2.array(removing:"Cat") print(array3) // ["Dog", "Turtle", "Fish"] 

Con las extensiones de protocolo puede hacer esto,

 extension Array where Element: Equatable { mutating func remove(object: Element) { if let index = indexOf({ $0 == object }) { removeAtIndex(index) } } } 

La misma funcionalidad para las classs,

Swift 2

 extension Array where Element: AnyObject { mutating func remove(object: Element) { if let index = indexOf({ $0 === object }) { removeAtIndex(index) } } } 

Swift 3

 extension Array where Element: AnyObject { mutating func remove(object: Element) { if let index = index(where: { $0 === object }) { remove(at: index) } } } 

Pero si una class implementa Equatable, se vuelve ambigua y el comstackdor da un error a los lanzamientos.

Con el uso de extensiones de protocolo en swift 2.0

 extension _ArrayType where Generator.Element : Equatable{ mutating func removeObject(object : Self.Generator.Element) { while let index = self.indexOf(object){ self.removeAtIndex(index) } } } 

¿Qué tal para usar el filtrado? lo siguiente funciona bastante bien incluso con [AnyObject].

 import Foundation extension Array { mutating func removeObject<T where T : Equatable>(obj: T) { self = self.filter({$0 as? T != obj}) } } 

Existe otra posibilidad de eliminar un elemento de una matriz sin tener un posible uso inseguro, ya que el tipo genérico del object a eliminar no puede ser el mismo que el tipo de la matriz. Usar optionals tampoco es la manera perfecta de ir, ya que son muy lentos. Por lo tanto, podría usar un cierre como ya se usa al orderar una matriz, por ejemplo.

 //removes the first item that is equal to the specified element mutating func removeFirst(element: Element, equality: (Element, Element) -> Bool) -> Bool { for (index, item) in enumerate(self) { if equality(item, element) { self.removeAtIndex(index) return true } } return false } 

Cuando extiende la class Array con esta function, puede eliminar elementos haciendo lo siguiente:

 var array = ["Apple", "Banana", "Strawberry"] array.removeFirst("Banana") { $0 == $1 } //Banana is now removed 

Sin embargo, incluso podría eliminar un elemento solo si tiene la misma dirección de memory (solo para classs que se ajustan al protocolo AnyObject , por supuesto):

 let date1 = NSDate() let date2 = NSDate() var array = [date1, date2] array.removeFirst(NSDate()) { $0 === $1 } //won't do anything array.removeFirst(date1) { $0 === $1 } //array now contains only 'date2' 

Lo bueno es que puedes especificar el parámetro para comparar. Por ejemplo, cuando tiene una matriz de matrices, puede especificar el cierre de igualdad como { $0.count == $1.count } y la primera matriz que tiene el mismo tamaño que la que se eliminará se elimina de la matriz.

Incluso podría acortar la llamada a la function al tener la function como function mutating func removeFirst(equality: (Element) -> Bool) -> Bool , luego reemplace la evaluación if con equality(item) y llame a la function por array.removeFirst({ $0 == "Banana" }) por ejemplo.

Usando indexOf lugar de a for o enumerate :

 extension Array where Element: Equatable { mutating func removeElement(element: Element) -> Element? { if let index = indexOf(element) { return removeAtIndex(index) } return nil } mutating func removeAllOccurrencesOfElement(element: Element) -> Int { var occurrences = 0 while true { if let index = indexOf(element) { removeAtIndex(index) occurrences++ } else { return occurrences } } } } 

Finalmente terminé con el siguiente código.

 extension Array where Element: Equatable { mutating func remove<Element: Equatable>(item: Element) -> Array { self = self.filter { $0 as? Element != item } return self } } 

[String:AnyObject] eliminar un [String:AnyObject] de una matriz [[String:AnyObject]] implementando un recuento fuera de un bucle for para representar el índice ya que .find y .filter no son compatibles con [String:AnyObject] .

 let additionValue = productHarvestChoices[trueIndex]["name"] as! String var count = 0 for productHarvestChoice in productHarvestChoices { if productHarvestChoice["name"] as! String == additionValue { productHarvestChoices.removeAtIndex(count) } count = count + 1 } 

Implementación en Swift 2:

 extension Array { mutating func removeObject<T: Equatable>(object: T) -> Bool { var index: Int? for (idx, objectToCompare) in self.enumerate() { if let toCompare = objectToCompare as? T { if toCompare == object { index = idx break } } } if(index != nil) { self.removeAtIndex(index!) return true } else { return false } } } 

Pude hacerlo funcionar:

 extension Array { mutating func removeObject<T: Equatable>(object: T) { var index: Int? for (idx, objectToCompare) in enumerate(self) { let to = objectToCompare as T if object == to { index = idx } } if(index) { self.removeAtIndex(index!) } } }