將滿足某條件的東西全部移除的 removeAll(where:) — Swift 4.2
Swift 4.2 多了function removeAll(where:),方便我們將滿足某條件的東西從 array 移除。這有什麼好呢 ?
讓我們先看看 removeAll(where:) 不存在時,一個很容易讓程式閃退的 for 寫法。在 roles array 裡有三個彼得潘故事的角色,好人彼得潘和壞人虎克跟鱷魚。我們希望童話故事裡只有好人,就像光良唱的,幸福和快樂是結局,所以我們利用 for 找出 array 裡 isGood 等於 false 的壞人,將他們從 array 移除。
struct Role { var name: String var isGood: Bool}var roles = [Role(name: "彼得潘", isGood: true), Role(name: "虎克", isGood: false), Role(name: "鱷魚", isGood: false)]for (i, role) in roles.enumerated() { if role.isGood == false { roles.remove(at: i) }}
然而程式卻閃退了。因為當我們要移除鱷魚時,array 已經因為之前移除虎克,數量變成 2,但鱷魚對應的 i 是 2,超過 array 成員的數量,造成 Index out of range。
此問題當然有方法可以解決,比方如以下例子利用 function filter 依序對 array 的成員執行參數 closure 的程式,回傳 true 的成員將組合成新的 array。
roles = roles.filter { (role) -> Bool in return role.isGood}
雖然此方法的結果是正確的,但有一些缺點。它的效能比較差,因為要產生一個新的 array。我們想要的只是把東西從原本的 array 移除,有那麼難嗎 ?
Swift 聽到了我們的心聲,在 4.2 發明 removeAll(where:) 幫助我們。
mutating func removeAll(where predicate: (Role) throws -> Bool) rethrows
removeAll 會依序對 array 的成員執行參數 closure 的程式,當回傳 true 時即代表此成員會被移除。因此在以下例子,壞人們都會被移除,只有好人可以繼續活在 array 裡。
roles.removeAll { (role) -> Bool in let isRemove = role.isGood == false return isRemove}
SE-0197 Adding in-place removeAll(where:) to the Standard Library