数组扩展以按值删除对象

Sno*_*man 140 arrays ios swift

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

但是,我收到了错误 var index = find(self, object)

'T'不能转换为'T'

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

'AnyObject'不能转换为'T'

这样做的正确方法是什么?

Mar*_*n R 166

Swift 2开始,这可以通过协议扩展方法实现. removeObject()被定义为符合RangeReplaceableCollectionType(特别是Array)所有类型的方法,如果集合的元素是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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

例:

var ar = [1, 2, 3, 2]
ar.removeObject(2)
print(ar) // [1, 3, 2]
Run Code Online (Sandbox Code Playgroud)

更新Swift 2/Xcode 7 beta 2:由于Airspeed Velocity在评论中注意到,现在实际上可以在对模板更具限制性的泛型类型上编写方法,因此该方法现在实际上可以定义为扩展的Array:

extension Array where Element : Equatable {

    // ... same method as above ...
}
Run Code Online (Sandbox Code Playgroud)

协议扩展仍然具有适用于更大类型的优点.

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • Swift 3版本很棒,但我会稍微将其声明重命名为`remove(object:Element)`以符合[Swift API设计指南](https://swift.org/documentation/api-design-准则/)并避免冗长.我提交了一份反映此内容的编辑. (2认同)

dre*_*wag 65

您不能在对模板更具限制性的泛型类型上编写方法.

:如雨燕2.0的,现在就可以编写方法在模板上更加严格.如果您已将代码升级到2.0,请进一步查看其他答案,以获取使用扩展实现此目的的新选项.

您收到错误的原因'T' is not convertible to 'T'是您实际上在方法中定义了一个与原始T无关的 T.如果您想在方法中使用T,则可以在方法中指定它.

您得到第二个错误的原因'AnyObject' is not convertible to 'T'是T的所有可能值都不是所有类.对于要转换为AnyObject的实例,它必须是一个类(它不能是struct,enum等).

你最好的办法是使它成为一个接受数组作为参数的函数:

func removeObject<T : Equatable>(object: T, inout fromArray array: [T]) {
}
Run Code Online (Sandbox Code Playgroud)

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

func arrayRemovingObject<T : Equatable>(object: T, fromArray array: [T]) -> [T] {
}
Run Code Online (Sandbox Code Playgroud)

作为我不推荐的替代方法,如果存储在数组中的类型无法转换为方法模板(即相等),则可以使方法无提示失败.(为清楚起见,我使用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]
Run Code Online (Sandbox Code Playgroud)

编辑为了克服沉默失败,你可以将成功作为一个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
Run Code Online (Sandbox Code Playgroud)

  • 在最新的迅速.`enumerate(self)`必须修复`self.enumerate()` (5认同)
  • 哇,写一个for循环来删除一个元素,回到90年代就是这样! (4认同)

Ján*_*nos 28

简要而简洁地说:

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

  • 注意使用force unwrapped索引,这可能是零.更改为"if let ind = index {array.removeAtIndex(ind)}" (11认同)
  • 这很酷.当然,也可以在没有`inout`的情况下完成.即使`inout`完好无损,我也可以使用`array = array.filter(){$ 0!= object}. (2认同)

ros*_*och 17

阅读以上所有内容后,我认为最好的答案是:

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

样品:

var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = arrayRemovingObject("Cat", fromArray:myArray )
Run Code Online (Sandbox Code Playgroud)

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

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

样品:

var myArray = ["Dog", "Cat", "Ant", "Fish", "Cat"]
myArray = myArray.arrayRemovingObject("Cat" )
Run Code Online (Sandbox Code Playgroud)

Swift 3.1更新

现在又回到了Swift 3.1.以下是一个扩展,提供详尽,快速,变异和创建变体.

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
    }
}
Run Code Online (Sandbox Code Playgroud)

样品:

// 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"]
Run Code Online (Sandbox Code Playgroud)


Sri*_*ala 13

使用协议扩展,您可以执行此操作,

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

类的功能相同,

斯威夫特2

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

斯威夫特3

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

但是如果一个类实现了Equatable,它就会变得模棱两可,编译器会抛出一个错误.


小智 7

在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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)