Swift:从数组中删除特定Object的更好方法是什么?

Bra*_*vos 3 arrays swift

我正在尝试使用我的代码更高效,但我有一个大脑放屁.我编写的这段代码非常有用,并且完全符合我的要求:它检查数组并删除未知索引处的Object.但我觉得有一种更好,更有效的方式来编写它.我去了Array.remove(at :),但这需要一个已知的索引.我正在进入大O符号,并且不知道如何使这更容易处理.有任何想法吗?

 // create a new object array
 var sort : [MyCustomObject] = []

//iterate through my object array  

        for i in objectArray{
            if i === objectToRemove{
            }
            else{
                sort.append(i)
            }
        }

     // set old array to sort, which no longer has the unwanted object 
        self.objectArray = sort
Run Code Online (Sandbox Code Playgroud)

vac*_*ama 9

使用firstIndex(where:)(以前index(where:)Swift 4.1及更早版本中调用)使用谓词在数组中搜索对象{ $0 === objectToRemove },然后调用remove(at:)数组将其删除:

if let idx = objectArray.firstIndex(where: { $0 === objectToRemove }) {
    objectArray.remove(at: idx)
}
Run Code Online (Sandbox Code Playgroud)

这允许您搜索您的对象是否是Equatable.

  • 请注意,firstIndex(where :)仍处于测试阶段(以前称为`index(where:)`) (2认同)

Leo*_*bus 6

如果您使用 Xcode 10.0+ beta(Swift 4.2 或更高版本)进行编码,则可以使用新方法 removeAll(where:)

mutating func removeAll(where predicate: (Element) throws -> Bool) rethrows
Run Code Online (Sandbox Code Playgroud)

讨论:使用此方法删除集合中满足特定条件的每个元素。 复杂度:O(n),其中 n 是集合的长度。

此示例从数字数组中删除所有奇数:

Swift 5.2 或更高版本

extension BinaryInteger {
    var isEven: Bool { isMultiple(of: 2) }
    var isOdd: Bool { !isMultiple(of: 2) }
}

var numbers = [5, 6, 7, 8, 9, 10, 11]
numbers.removeAll(where: \.isOdd) // numbers == [6, 8, 10]
numbers
Run Code Online (Sandbox Code Playgroud)

在您的情况下,请确保MyCustomObject符合Equatable

objectArray.removeAll(where: { $0 == objectToRemove })
Run Code Online (Sandbox Code Playgroud)

或使用符合它的属性之一作为谓词(即id: Int):

objectArray.removeAll(where: { $0.id == idToRemove })
Run Code Online (Sandbox Code Playgroud)

注意:如果您没有使用 Xcode 10.0+ beta (Swift 4.2),您可以实现您自己的removeAll(where:)方法,如您在此答案中所见。


实现 a removeFirst(where:)andremoveLast(where:)避免迭代整个集合,如@vacawama 的评论中所述

斯威夫特 4.1

extension RangeReplaceableCollection  {
    @discardableResult
    mutating func removeFirst(where predicate: (Element) throws -> Bool) rethrows -> Element?  {
        guard let index = try index(where: predicate) else { return nil }
        return remove(at: index)
    }
}
Run Code Online (Sandbox Code Playgroud)
extension RangeReplaceableCollection where Self: BidirectionalCollection {
    @discardableResult
    mutating func removeLast(where predicate: (Element) throws -> Bool) rethrows -> Element? {
        guard let index = try indices.reversed().first(where: {
            try predicate(self[$0])
        }) else { return nil }
        return remove(at: index)
    }
}
Run Code Online (Sandbox Code Playgroud)

Swift 4.2 或更高版本(如@Hamish 所建议)

extension RangeReplaceableCollection {
    @discardableResult
    mutating func removeFirst(where predicate: (Element) throws -> Bool) rethrows -> Element? {
        guard let index = try firstIndex(where: predicate) else { return nil }
        return remove(at: index)
    }
}
Run Code Online (Sandbox Code Playgroud)
extension RangeReplaceableCollection where Self: BidirectionalCollection {
    @discardableResult
    mutating func removeLast(where predicate: (Element) throws -> Bool) rethrows -> Element? {
        guard let index = try lastIndex(where: predicate) else { return nil }
        return remove(at: index)
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以查看这篇文章中的 remove(while:)、removeLast(while:) 和 dropLast(while:) 方法实现。