【问题标题】:Removing object from array in Swift 3从 Swift 3 中的数组中删除对象
【发布时间】:2017-04-13 01:07:24
【问题描述】:

在我的应用程序中,我在选择单元格时在数组中添加了一个对象,在重新选择单元格时取消选择并删除对象。我使用了那个代码,但给了我错误。

extension Array {
    func indexOfObject(object : AnyObject) -> NSInteger {
        return (self as NSArray).indexOfObject(object)
    }

    mutating func removeObject(object : AnyObject) {
        for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) {
            self.removeAtIndex(index)
        }
    }
}

class MyViewController: UITableViewController {
    var arrContacts: [Any] = []
    var contacts: [Any] = []

    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        arrContacts.removeObject(contacts[indexPath.row])
    }
}

它给了我 2 个这样的错误:

C-style for statement has been removed in Swift 3
Value of type '[Any]' has no member 'removeObject'

【问题讨论】:

  • 您可以使用Set<Contact> 而不是数组。您能否提供有关您的联系对象的更多信息?如果您自己制作,则需要符合 HashableEquatable 才能将其放入集合中

标签: ios arrays swift swift3


【解决方案1】:

在 Swift 3 中试试这个

array.remove(at: Index)

代替

array.removeAtIndex(index)

更新

"Declaration is only valid at file scope".

确保对象在范围内。您可以指定范围“内部”,这是默认值。

index(of:<Object>) 上班,上课要符合Equatable

【讨论】:

    【解决方案2】:

    相当于NSMutableArrayremoveObject的Swift是:

    var array = ["alpha", "beta", "gamma"]
    
    if let index = array.firstIndex(of: "beta") {
        array.remove(at: index)
    }
    

    如果对象是唯一的。完全不需要转换为NSArray 并使用indexOfObject:

    API index(of: 也可以使用,但这会导致不必要的隐式桥接强制转换为 NSArray

    如果同一对象多次出现,请使用filter。但是,在索引与特定对象关联的数据源数组等情况下,firstIndex(of 更可取,因为它比filter 更快。

    更新:

    在 Swift 4.2+ 中,您可以使用 removeAll(where:) 删除一次或多次出现的 beta

    array.removeAll{$0 == "beta"}
    

    【讨论】:

    • 这是最好的答案,但是没有 remove(object: "beta") 实在是太愚蠢了。
    • 我认为 .index(of: 只有在集合包含 Equatable 类型时才可用。
    • @AdamWaite 是的,但这也适用于 Foundation 类型。
    • 这是不对的,如果你有多个“测试版”怎么办?这仅在数组不包含多次出现时才有效。正确答案是使用过滤器或稍后运行此答案,while let index = array.index(of: "beta") { array.remove(at: index) }
    • @juancazalla 你是对的,但是如果数组可以包含多个匹配项,请使用filter 解决方案。但是,如果对象是唯一的,请始终使用 index(of,因为它比 filter 性能更高
    【解决方案3】:
    1. for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) 是 C 风格的 for 循环,已被移除

    2. 将您的代码更改为类似这样的内容,以删除所有已循环的类似对象:

      let indexes = arrContacts.enumerated().filter { $0.element == contacts[indexPath.row] }.map{ $0.offset }
      for index in indexes.reversed() {
         arrContacts.remove(at: index)
      }
      

    【讨论】:

    • enumerated -> filter -> map and remove(at) 是聪明的解决方案。推荐这个
    【解决方案4】:

    在 Swift 3 中从这些对象的数组(名为“array”)中删除唯一对象(名为“objectToRemove”)的正确且有效的单行解决方案是:

    if let index = array.enumerated().filter( { $0.element === objectToRemove }).map({ $0.offset }).first {
       array.remove(at: index)
    }
    

    【讨论】:

      【解决方案5】:

      另一个不错且有用的解决方案是创建这种扩展:

      extension Array where Element: Equatable {
      
          @discardableResult mutating func remove(object: Element) -> Bool {
              if let index = index(of: object) {
                  self.remove(at: index)
                  return true
              }
              return false
          }
      
          @discardableResult mutating func remove(where predicate: (Array.Iterator.Element) -> Bool) -> Bool {
              if let index = self.index(where: { (element) -> Bool in
                  return predicate(element)
              }) {
                  self.remove(at: index)
                  return true
              }
              return false
          }
      
      }
      

      这样,如果您的数组带有自定义对象:

      let obj1 = MyObject(id: 1)
      let obj2 = MyObject(id: 2)
      var array: [MyObject] = [obj1, obj2]
      
      array.remove(where: { (obj) -> Bool in
          return obj.id == 1
      })
      // OR
      array.remove(object: obj2) 
      

      【讨论】:

      • 这仅适用于数组不包含多次出现的情况。正确的答案是使用过滤器或在一段时间内运行此答案。作为此扩展程序的用户,我希望它能够删除所有出现的事件,而不仅仅是一个
      • 很好,但应该是remove(element: Element),因为在 Array 中您还可以存储 Int、Double 等类型 - 它们不是对象。
      【解决方案6】:
      var a = ["one", "two", "three", "four", "five"]
      
      // Remove/filter item with value 'three'
      a = a.filter { $0 != "three" }
      

      【讨论】:

      • 这是正确的 Swift 解决方案,它利用了该语言提供的语法优势。
      • 如果 item 是一个对象怎么办?
      • @TomSawyer 过滤掉一个对象,使用 $0 !==
      【解决方案7】:

      对于 Swift 3,您可以使用 index(where:) 并包含一个闭包,该闭包将数组 ($0) 中的对象与您要查找的对象进行比较。

      var array = ["alpha", "beta", "gamma"]
      if let index = array.index(where: {$0 == "beta"}) {
        array.remove(at: index)
      }
      

      【讨论】:

      • 如果我想删除多个对象,这会起作用吗?喜欢(其中:{$0 == "beta" || $0 == "gamma" })
      【解决方案8】:

      斯威夫特 4

      var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
      
      if let index = students.firstIndex(where: { $0.hasPrefix("A") }) {
         students.remove(at: index)
      }
      

      【讨论】:

        【解决方案9】:

        Swift 5 中,使用 Extension:

        extension Array where Element: Equatable{
            mutating func remove (element: Element) {
                if let i = self.firstIndex(of: element) {
                    self.remove(at: i)
                }
            }
        }
        

        示例:

        var array = ["alpha", "beta", "gamma"]
        array.remove(element: "beta")
        

        Swift 3 中,使用这个Extension

        extension Array where Element: Equatable{
            mutating func remove (element: Element) {
                if let i = self.index(of: element) {
                    self.remove(at: i)
                }
            }
        }
        

        示例:

        var array = ["alpha", "beta", "gamma"]
        array.remove(element: "beta")
        

        【讨论】:

          【解决方案10】:

          数组的扩展可以轻松完成并允许 Swift 4.2 及更高版本的链接:

          public extension Array where Element: Equatable {
              @discardableResult
              public mutating func remove(_ item: Element) -> Array {
                  if let index = firstIndex(where: { item == $0 }) {
                      remove(at: index)
                  }
                  return self
              }
          
              @discardableResult
              public mutating func removeAll(_ item: Element) -> Array {
                  removeAll(where: { item == $0 })
                  return self
              }
          }
          

          【讨论】:

          • 参数标签 '(where:)' 不匹配任何可用的重载
          • @jeet.chanchawat 那么可能不同的 swift 版本......哦,这个问题是针对 3 的?好吧,我想我在写这篇文章的时候有 4.2,但现在不记得了,以后会检查它,它肯定对我有用
          【解决方案11】:

          Swift 3 和 4

          var array = ["a", "b", "c", "d", "e", "f"]
          
          for (index, element) in array.enumerated().reversed() {
              array.remove(at: index)
          }
          

          Swift 4.2 开始,您可以使用更高级的方法(更快且内存效率更高)

          array.removeAll(where: { $0 == "c" })
          

          而不是

          array = array.filter { !$0.hasPrefix("c") }
          

          阅读更多here

          【讨论】:

            【解决方案12】:

            这是查找特定对象索引的官方答案,然后您可以使用该索引轻松删除任何对象:

            var students = ["Ben", "Ivy", "Jordell", "Maxime"]
            if let i = students.firstIndex(of: "Maxime") {
                 // students[i] = "Max"
                 students.remove(at: i)
            }
            print(students)
            // Prints ["Ben", "Ivy", "Jordell"]
            

            这里是链接:https://developer.apple.com/documentation/swift/array/2994720-firstindex

            【讨论】:

              【解决方案13】:

              这是我用过的(Swift 5)...

                  extension Array where Element:Equatable
                  {
                      @discardableResult
                      mutating func removeFirst(_ item:Any ) -> Any? {
                          for index in 0..<self.count {
                              if(item as? Element == self[index]) {
                                  return self.remove(at: index)
                              }
                          }
                          return nil
                      }
                      @discardableResult
                      mutating func removeLast(_ item:Any ) -> Any? {
                          var index = self.count-1
                          while index >= 0 {
                              if(item as? Element == self[index]) {
                                  return self.remove(at: index)
                              }
                              index -= 1
                          }
                          return nil
                      }
                  }
              
                  var arrContacts:[String] = ["A","B","D","C","B","D"]
                  var contacts: [Any] = ["B","D"]
                  print(arrContacts)
                  var index = 1
                  arrContacts.removeFirst(contacts[index])
                  print(arrContacts)
                  index = 0
                  arrContacts.removeLast(contacts[index])
                  print(arrContacts)
              

              结果:

                 ["A", "B", "D", "C", "B", "D"]
                 ["A", "B", "C", "B", "D"]
                 ["A", "B", "C", "D"]
              

              重要提示:从中移除项的数组必须包含 Equatable 元素(如对象、字符串、数字等)

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2018-01-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-10-27
                • 1970-01-01
                • 2021-08-14
                相关资源
                最近更新 更多