Swift: лучший способ удалить конкретный объект из массива? - PullRequest
0 голосов
/ 28 августа 2018

Я пытаюсь быть более эффективным с моим кодом, но у меня пукает мозг. Этот код, который я написал, прекрасно работает и делает именно то, что мне нужно: он проверяет массив и удаляет объект с неизвестным индексом. Но я чувствую, что есть лучший, более эффективный способ написать это. Я пошел в Array.remove (at :), но это требует известного индекса. Я вхожу в большой нотации и не знаю, как сделать это проще для обработки. Есть идеи?

 // 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

Ответы [ 4 ]

0 голосов
/ 29 августа 2018

Свифт 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"]

Edit:

Или, может быть, еще лучше, используйте фильтр:

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"]
0 голосов
/ 28 августа 2018

Используйте firstIndex(where:) (ранее называвшийся index(where:) в Swift 4.1 и более ранних), чтобы найти в массиве объект с помощью предиката { $0 === objectToRemove }, затем вызвать remove(at:) в массиве, чтобы удалить его:

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

Это позволяет вам искать ваш объект, Equatable или нет.

0 голосов
/ 29 августа 2018

Если вы кодируете с помощью 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:), как вы можете видеть в этом ответе .


Реализация removeFirst(where:) и removeLast(where:), чтобы избежать итерации всей Коллекции, как указано в комментариях @ vacawama

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)
    }
}
0 голосов
/ 28 августа 2018

Вы можете попробовать

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