Вопрос:

Удалить соответствующий элемент из массива объектов?

arrays swift

6571 просмотра

4 ответа

10656 Репутация автора

У меня есть массив таких объектов:

var myArr = [
  MyObject(name: "Abc", description: "Lorem ipsum 1."),
  MyObject(name: "Def", description: "Lorem ipsum 2."),
  MyObject(name: "Xyz", description: "Lorem ipsum 3.")
]

Я знаю, что могу найти подобранный предмет, как это:

var temp = myArr.filter { $0.name == "Def" }.first

Но теперь, как мне удалить его из оригинала myArr? Я надеялся, что filter.firstможет вернуть индекс как-нибудь, чтобы я мог использовать removeAtIndex. Или еще лучше, я хотел бы сделать что-то вроде этого:

myArr.removeAll { $0.name == "Def" } // Pseudo

Есть идеи?

Автор: TruMan1 Источник Размещён: 16.04.2015 02:39

Ответы (4)


1 плюс

8810 Репутация автора

Получите объекты, используя фильтр, затем переберите массив и используйте myArr.removeAtIndex (index), чтобы удалить каждый объект. Использование фильтра делает именно это. Чтобы понять, что происходит, читайте ниже. Ответ Matts - намного более чистый способ сделать это, так как вы проверяете на противоположное соответствие, поэтому каждый объект сохраняется, если он не соответствует вашему значению.

Цикл вашего массива временных фильтров

if let index = find(temp, note) {
   myArr.removeAtIndex(index)
}
Автор: Mark McCorkle Размещён: 16.04.2015 02:41

16 плюса

364258 Репутация автора

Решение

Что вы не понимаете, так это то, что Array является структурой и, следовательно, является типом значения . Он не может быть видоизменен так, как может быть экземпляр класса. Таким образом, вы всегда будете создавать новый массив за кулисами, даже если вы расширите Array для написания мутирующего removeIfметода.

Таким образом, нет никаких недостатков и нет потери общности в использовании filterи логического отрицания вашего состояния закрытия:

myArr = myArr.filter { $0.name != "Def" }

Например, вы можете написать removeIfтак:

extension Array {
    mutating func removeIf(closure:(T -> Bool)) {
        for (var ix = self.count - 1; ix >= 0; ix--) {
            if closure(self[ix]) {
                self.removeAtIndex(ix)
            }
        }
    }
}

И тогда вы можете использовать это так:

myArr.removeIf {$0.name == "Def"}

Но на самом деле это большая жирная трата вашего времени. Вы здесь ничего не делаете, чего filterеще не делаете. Он может появиться из myArr.removeIfсинтаксиса , который вы мутагенные myArrна месте, но вы не; вы заменяете его другим массивом. Действительно, каждый вызов removeAtIndexв этом цикле создает другой массив! Так что вы можете использовать filterи быть счастливым.

Автор: matt Размещён: 16.04.2015 02:49

1 плюс

49054 Репутация автора

если вы хотите удалить объект из массива, который итерируется, вы должны всегда выполнять итерацию в обратном направлении, иначе вы в какой-то момент будете работать с индексами, которые больше не действительны.

var myArr = [
    ["key":"value1"],
    ["key":"value2"],
    ["key":"value3"]
]

for index in stride(from: myArr.count - 1 , to: 0, by: -1){
    let x = myArr[index]
    if x["key"] == "value2"{
        myArr.removeAtIndex(index)
    }
}
Автор: VikingoS says Reinstate Monica Размещён: 16.04.2015 03:03

1 плюс

111 Репутация автора

Apple добавила то, что вы хотите в Swift 4:

var phrase = "The rain in Spain stays mainly in the plain."
let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
phrase.removeAll(where: { vowels.contains($0) })
// phrase == "Th rn n Spn stys mnly n th pln."
Автор: YuLong Xiao Размещён: 04.04.2019 03:18
Вопросы из категории :
32x32