数组扩展以按值删除对象

 小p揪脸包918 发布于 2023-01-01 12:43

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

例:

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

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

extension Array where Element : Equatable {

    // ... same method as above ...
}

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

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

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


drewag.. 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(object: T, inout fromArray array: [T]) {
}

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

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

作为我不推荐的替代方法,如果存储在数组中的类型无法转换为方法模板(即相等),则可以使方法无提示失败.(为清楚起见,我使用U而不是T作为方法的模板):

extension Array {
    mutating func removeObject(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]

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

extension Array {
  mutating func removeObject(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

在最新的迅速.`enumerate(self)`必须修复`self.enumerate()` (5认同)

哇,写一个for循环来删除一个元素,回到90年代就是这样! (4认同)


János.. 28

简要而简洁地说:

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

注意使用force unwrapped索引,这可能是零.更改为"if let ind = index {array.removeAtIndex(ind)}" (11认同)

这很酷.当然,也可以在没有`inout`的情况下完成.即使`inout`完好无损,我也可以使用`array = array.filter(){$ 0!= object}. (2认同)


rosstulloch.. 17

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

func arrayRemovingObject(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.以下是一个扩展,提供详尽,快速,变异和创建变体.

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


小智.. 13

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

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

类的功能相同,

斯威夫特2

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

斯威夫特3

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

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

6 个回答
  • 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)
            }
        }
    }
    

    例:

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

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

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

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

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

    2023-01-01 12:44 回答
  • 简要而简洁地说:

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

    2023-01-01 12:45 回答
  • 阅读以上所有内容后,我认为最好的答案是:

    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.以下是一个扩展,提供详尽,快速,变异和创建变体.

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

    2023-01-01 12:45 回答
  • 使用协议扩展,您可以执行此操作,

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

    类的功能相同,

    斯威夫特2

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

    斯威夫特3

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

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

    2023-01-01 12:45 回答
  • 您不能在对模板更具限制性的泛型类型上编写方法.

    :如雨燕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]) {
    }
    

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

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

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

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

    2023-01-01 12:45 回答
  • 在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)
            }
        }
    }
    

    2023-01-01 12:47 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有