Swift:从数组中删除特定对象的更好方法?

时间:2018-08-28 19:55:32

标签: arrays swift

我正在尝试提高代码效率,但我却脑子发疯。我编写的这段代码很好用,并且完全满足我的需要:它检查一个数组,并删除一个未知索引处的Object。但是我觉得有一种更好,更有效的编写方法。我去了Array.remove(at :),但这需要一个已知的索引。我正在使用大的O表示法,并且不知道如何使其更易于处理。有什么想法吗?

function clearRange() {
  var sheet = SpreadsheetApp.getActive().getSheetByName('inventaire');
  sheet.getRange('B3:E8').clearContent();
}

5 个答案:

答案 0 :(得分:8)

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

if let idx = objectArray.firstIndex(where: { $0 === objectToRemove }) {
    objectArray.remove(at: idx)
}

这使您可以搜索对象是否为Equatable

答案 1 :(得分:3)

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

mutating func removeAll(where predicate: (Element) throws -> Bool) rethrows
  

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

     

此示例将所有奇数删除   数值数组中的值:

var numbers = [5, 6, 7, 8, 9, 10, 11]
numbers.removeAll(where: { $0 % 2 == 1 }) // numbers == [6, 8, 10]

对于您而言,请确保MyCustomObject符合Equatable

objectArray.removeAll(where: { $0 == objectToRemove })

或使用确实符合它的条件之一作为谓词(即id: Int):

objectArray.removeAll(where: { $0.id == idToRemove })

注意::如果您不使用Xcode 10.0+ Beta(Swift 4.2),则可以实现自己的removeAll(where:)方法,如本answer所示。 >


实施removeFirst(where:)removeLast(where:)以避免迭代@vacawama的评论中提到的整个Collection

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

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

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

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

答案 2 :(得分:0)

您可以尝试

if let ind = objectArray.index(of:objectToRemove) {
  objectArray.remove(at:ind)
}

答案 3 :(得分:0)

您可以使用此泛型从数组中删除任何类型的对象

extension Array where Element: Equatable {
mutating func removeObject(object: Element)  {
    if let index = firstIndex(of: object) {
        remove(at: index)
    }
}}

答案 4 :(得分:-1)

雨燕4

使用enumerated(),您将获得索引:

var array = ["a","b","c"]
let objectToRemove = "b"
for (index, value) in array.enumerated() {
    if value == objectToRemove {
        array.remove(at: index)
    }
}
print(array) // Prints: ["a","c"]

编辑:

也许更好,使用过滤器:

var array = ["a","b","c"]
let objectToRemove = "b"
array = array.filter { $0 != objectToRemove } // Keeps only what is
                                              // different from the 
                                              // objectToRemove
print(newArray)  // Prints: ["a","c"]