数组扩展名,用于按值删除对象

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

但是,我得到一个错误var index = find(self, object)

'T'不能转换为'T'

我也试过用这个方法签名: func removeObject(object: AnyObject) ,但是,我得到了同样的错误:

“AnyObject”不能转换为“T”

什么是正确的方法来做到这一点?

Swift 2开始 ,这可以通过协议扩展方法来实现。 如果集合的元素是可Equatable removeObject()被定义为符合RangeReplaceableCollectionType (特别是在Array )的所有types的方法:

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

例:

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

Swift 2 / Xcode 7 beta 2的更新:在注释中注意到Airspeed Velocity,现在实际上可以在generics上编写一个对模板更加严格的方法,所以现在这个方法实际上可以定义为扩展Array

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

协议扩展仍然具有适用于更大types的优点。

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

您不能在模板上对限制性更强的genericstypes编写方法。

注意 :从Swift 2.0开始,现在可以编写对模板更严格的方法。 如果您已将代码升级到2.0,请参阅其他答案,以获取使用扩展实现此选项的新选项。

你得到错误'T' is not convertible to 'T'的原因'T' is not convertible to 'T'是,你实际上在你的方法中定义了一个新的 T,与原来的T无关。如果你想在你的方法中使用T,可以这样做,而不用在你的方法中指定它。

你得到第二个错误'AnyObject' is not convertible to 'T''AnyObject' is not convertible to 'T'所有可能的值不是所有的类。 对于要转换为AnyObject的实例,它必须是一个类(它不能是一个结构,枚举等)。

你最好的select是把它作为一个接受数组作为参数的函数:

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

或者不是修改原始数组,而是通过返回一个副本使您的方法更安全,更可重用:

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

作为我不build议的替代方法,如果存储在数组中的types无法转换为方法模板(可以是equatable),则可以使方法失败。 (为了清楚起见,我使用U而不是T来表示方法的模板):

 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] 

编辑为了克服沉默失败,你可以作为一个布尔返回成功:

 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 

简要而简洁地说:

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

看完以上所有内容,我的脑海中最好的答案是:

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

样品:

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

Swift 2(xcode 7b4)数组扩展:

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

样品:

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

Swift 3.1更新

现在回到这个Swift 3.1已经出来了。 下面是一个扩展,提供详尽,快速,变异和创build变种。

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

样品:

 // 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"] 

有了协议扩展,你可以做到这一点,

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

类的function相同,

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

但是如果一个类实现了Equatable,它会变得不明确,编译器会给出一个错误。

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

什么使用过滤? 即使使用[AnyObject],以下工作也相当顺利。

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

还有另外一种可能性,即从一个数组中删除一个项目,而不会有不安全的使用,因为要删除的对象的genericstypes不能和数组types相同。 使用可选项也不是完美的方式,因为它们很慢。 因此,您可以使用一个闭包,就像它在sorting数组时已经使用的那样。

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

当用这个函数扩展Array类时,可以通过执行以下操作来删除元素:

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

但是,你甚至可以删除一个元素,只要它具有相同的内存地址(当然,只适用于符合AnyObject协议的类):

 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' 

好的是,你可以指定要比较的参数。 例如,当你有一个数组的数组时,你可以指定相等的闭包为{ $0.count == $1.count } ,第一个数组的大小和要移除的大小相同。

你甚至可以通过调用mutating func removeFirst(equality: (Element) -> Bool) -> Bool代替函数调用,然后用equality(item)replacemutating func removeFirst(equality: (Element) -> Bool) -> Bool评估,并通过array.removeFirst({ $0 == "Banana" })

使用indexOf而不是forenumerate

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

我终于结束了以下代码。

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

由于.find.filter[String:AnyObject]不兼容,我通过在for循环之外实现一个计数来表示索引, .find从数组[[String:AnyObject]] .filter [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 } 

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

我能够得到它的工作:

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