【问题标题】:drop(where: {}) remove(where: {}) function in Swift?Swift 中的 drop(where: {}) remove(where: {}) 函数?
【发布时间】:2018-05-04 09:05:40
【问题描述】:

在 Swift 标准库中是否有一个函数作用于集合,接受一个谓词并返回从该集合中删除的值?

目前,我必须分两步实现它:

guard let idx = allAnnotations.index(where: {$0 is MKUserLocation}) else {return}
let userLocation = allAnnotations.remove(at: idx) as! MKUserLocation

但我猜,存在类似的功能。

目标

我有以下数组:

[Type1, Type1, Type1, Type1, Type1, Type1, Type2]

Type2 可能存在也可能不存在于数组中。除了这两种之外,没有其他类型。

我需要把它分成两个元素:

[Type1, Type1, Type1, Type1, Type1, Type1]

Type2?

这就是我要找的功能。

【问题讨论】:

  • 听起来你在找filter()
  • 如果多个元素与谓词匹配,会发生什么?目前您正在删除第一个。
  • @vikingosegundo true,过滤器已关闭。我已经更新了这个问题以进一步澄清它。
  • 如果Type2有多个元素,Type3也有一些元素怎么办?
  • @PuneetSharma 是的,没关系。 Type2 可能只有一个元素。特别是,我将[MKAnnotation] 拆分为我的自定义注释和MKUserLocation 注释的数组。

标签: arrays swift collections


【解决方案1】:

Swift 5 有removeAll(where)

@inlinable public mutating func removeAll(where shouldBeRemoved: (Element) throws -> Bool) rethrows

你可以这样使用它-

var array = [1,2,3]
array.removeAll(where: { $0 == 2})
print(array) // [1,3]

Apple Docs

【讨论】:

  • 感谢您的回答,我将其标记为已接受,因为 Swift 5 现在是主流。我的问题是在 Swift 5 之前写的。
【解决方案2】:

这是一个返回被删除元素数组的扩展:

extension Array {
    mutating func dropWhere(_ isIncluded: (Element) throws -> Bool) -> [Element] {
        do {
            let reverseArray = try filter { try isIncluded($0) }
            self = try filter { try !isIncluded($0) }

            return reverseArray
        } catch {
            return []
        }
    }
}

就像调用 filter 一样调用它。

var array = [1, 2, 3]
let array2 = array.dropWhere { $0 > 2 }
print(array) //[1, 2]
print(array2) //[3]

【讨论】:

    【解决方案3】:

    我完成的代码:

    extension Array {
      mutating func popFirstElementWith(_ predicate:(Element)->(Bool)) -> Element? {
        for (idx, element) in enumerated() {
          if predicate(element) {
            remove(at: idx)
            return element
          }
        }
        return nil
      }
    }
    

    【讨论】:

      【解决方案4】:

      你可以使用Split,条件是对你的数组进行切片

          var typeList =  [Type1, Type1, Type1, Type1, Type1, Type1, Type2]
      
          var slicedArray:[ArraySlice] = typeList.split { (value) -> Bool in
                      return value == YourCondition
                  }
      print(slicedArray)
      

      【讨论】:

      • 如果Type2 的元素不在数组的开头/结尾,Split 将不起作用。
      【解决方案5】:

      这个扩展接受一个谓词,如果它与谓词匹配,则返回元素。此外,从数组中删除元素。

      extension Array {
          mutating func popFirstElementWith(_ predicate:(Element)->(Bool)) -> Element? {
              var firstElement:Element?
              self = self.compactMap({ (element:Element) -> Element? in
                  guard predicate(element) == true else {
                      return element
                  }
                  if firstElement == nil {
                      firstElement = element
                  }
                  return nil
              })
              return firstElement
          }
      }
      

      测试:

      var array:[Any] = ["a", "b", 1, "c"]
      let element = array.popFirstElementWith { (element) -> (Bool) in
          return element is Int
      }
      print(element!)
      print(array)
      

      输出

      1
      ["a", "b", "c"]
      

      【讨论】:

      • 谢谢。虽然 Swift 标准库没有这样的功能,但我已经接受了你的回答。这正是我们所需要的。
      • 我对你的代码做了一些修改,请看下面我的回答。
      • @RichardTopchiy:在您的代码中,您将删除找到的第一个与谓词匹配的元素并返回。我想,如果这是你想要的,那很好。
      • 没错,它的工作方式与您的示例完全相同。这对我的任务来说很好,因为我只有一个要移除的对象。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-25
      • 1970-01-01
      • 2016-02-02
      • 2018-08-01
      • 1970-01-01
      相关资源
      最近更新 更多